■ USB通信2                                                         

  ■ PIC18F14K50 HIDクラス LED 点灯/消灯制御&表示
   
  
 <試作品仕様>
  ・PC(Windows)上のボタンスイッチ×4個をクリックすると PIC18F40K50のキバン上の対応するLEDがON/OFFすること
  ・PCとPIC間のUSB通信はHIDクラスとする。
  ・ボタンスイッチはLEDがONしているときは赤色、OFFの時は灰色とする。
  ・USB通信ONのボタンボタンスイッチをフォーム上にもうけること。 またUSB通信が確立したら”接続完了!”の文字をテキストボックスに表示のこと

 ★ PC側のソフト(Windows)は こちらを参照願います 
   
<試作品回路図>(→回路図のPDFファイル

 




<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています

     

          

   <プログラム例>


//Ledx4 オンオフ制御
//PIC18F14K50

#include "usb.h"
#include "HardwareProfile.h"
#include "usb_function_hid.h"

//システムクロック48MHz(= 12MHz x 4PLL)
#pragma config CPUDIV = NOCLKDIV ,USBDIV = OFF, PCLKEN = ON
#pragma config FOSC = HS, PLLEN = ON, HFOFST = OFF
#pragma config PWRTEN = ON, BOREN = OFF, MCLRE = OFF, BORV = 30
#pragma config WDTEN = OFF, LVP = OFF, FCMEN = OFF, IESO = OFF
#pragma config CP0 = OFF, XINST = OFF

// USB関連バッファ、変数定義
#pragma udata usbram2
unsigned char ReceivedDataBuffer[64];
unsigned char SendBuf[64];
#pragma udata
USB_HANDLE USBOutHandle = 0;
USB_HANDLE USBInHandle = 0;
BOOL blinkStatusValid = TRUE;
//グローバル変数定義
BYTE  counter;
BOOL  blinkStatusValid;

//コマンド定数定義
typedef enum
{
    CHECK       = 0x30,
    POUT        = 0x31,
    PIN         = 0x32,
    AIN         = 0x33,
    RESET       = 0xFF

}TYPE_CMD;

void BlinkUSBStatus(void);
void ProcessIO(void);
void YourHighPriorityISRCode();
void YourLowPriorityISRCode();
void USBCBSendResume(void);

// 割り込みベクタ定義
#pragma code REMAPPED_HIGH_INTERRUPT_VECTOR = 0x08
void Remapped_High_ISR (void)
{
     _asm goto YourHighPriorityISRCode _endasm
}
#pragma code REMAPPED_LOW_INTERRUPT_VECTOR = 0x18
void Remapped_Low_ISR (void)
{
     _asm goto YourLowPriorityISRCode _endasm
}

// 割り込み処理関数
#pragma code
#pragma interrupt YourHighPriorityISRCode
void YourHighPriorityISRCode()
{
        USBDeviceTasks();
}
#pragma interruptlow YourLowPriorityISRCode
void YourLowPriorityISRCode()
{
}

#pragma code
void main(void)
{
        
        ANSEL = 0x00;   // デジタルに設定
        TRISC = 0;      //LEDポート(RC0-RC3) :out
        LATC = 0;       //全LED消灯

        //USB関連
        USBDeviceInit();                                // USB初期化
        USBInHandle = 0;
        USBOutHandle = 0;
        blinkStatusValid = TRUE;                // USB目印LED有効化
        USBDeviceAttach();                      // USB割り込み有効化

        
    while(1)
    {
                //USB接続中なら送受信実行
                if((USBDeviceState >= CONFIGURED_STATE)&&(USBSuspendControl!=1))
                        ProcessIO();                            // コマンド実行
        }
}

//ユーザーアプリの入出力処理関数
void ProcessIO(void)
{
        //データ受信処理
        if(!HIDRxHandleBusy(USBOutHandle))
        {
                blinkStatusValid = FALSE;
                SendBuf[0] = ReceivedDataBuffer[0];
                SendBuf[1] = ReceivedDataBuffer[1];
                //コマンドの処理
                switch(ReceivedDataBuffer[0])   // コマンドコードチェック   //受信データの先頭バイトチェック
                {
                        //接続確認応答
                        case CHECK: //0x30
                                SendBuf[2] = 'O';
                                SendBuf[3] = 'K';
                                if(!HIDTxHandleBusy(USBInHandle))
                                        USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&SendBuf[0],64);
                                break;
                        //LED制御の場合
                        case POUT:  //0x31,
                                if(ReceivedDataBuffer[1] == 0x31){  //LED0の場合
                                        if(ReceivedDataBuffer[2] == 0x31)
                                        {       mLED_1_On();            }   //LED:ON
                                        else if(ReceivedDataBuffer[2] == 0x30)
                                        {       mLED_1_Off();   }           //LED:OFF
                                        SendBuf[2] = mLED_1 + 0x30;
                                }
                                else if(ReceivedDataBuffer[1] == 0x32){ //LED1の場合
                                        if(ReceivedDataBuffer[2] == 0x31)
                                        {       mLED_2_On();            }
                                        else if(ReceivedDataBuffer[2] == 0x30)
                                        {       mLED_2_Off();   }
                                        SendBuf[2] = mLED_2 + 0x30;
                                }
                                else if(ReceivedDataBuffer[1] == 0x33){ //LED2の場合
                                        if(ReceivedDataBuffer[2] == 0x31)
                                        {       mLED_3_On();            }
                                        else if(ReceivedDataBuffer[2] == 0x30)
                                        {       mLED_3_Off();   }
                                        SendBuf[2] = mLED_3 + 0x30;
                                }
                                else if(ReceivedDataBuffer[1] == 0x34){ //LED3の場合
                                        if(ReceivedDataBuffer[2] == 0x31)
                                        {       mLED_4_On();            }
                                        else if(ReceivedDataBuffer[2] == 0x30)
                                        {       mLED_4_Off();   }
                                        SendBuf[2] = mLED_4 + 0x30;
                                }
                                if(!HIDTxHandleBusy(USBInHandle))
                                        USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&SendBuf[0],64);
                                break;
                        default:
                                break;
                }
                // 次の受信実行
                USBOutHandle = HIDRxPacket(HID_EP,(BYTE*)&ReceivedDataBuffer,64);
        }
}


/******************************************************************
************** USB Callback Functions *****************************
*******************************************************************/
/******************************************************************
 * Function:        void USBCBSuspend(void)
 ******************************************************************/
void USBCBSuspend(void)
{
}
/*******************************************************************
 * Function:        void USBCBWakeFromSuspend(void)
 *******************************************************************/
void USBCBWakeFromSuspend(void)
{
}
/********************************************************************
 * Function:        void USBCB_SOF_Handler(void)
 *******************************************************************/
void USBCB_SOF_Handler(void)
{
}
/*******************************************************************
 * Function:        void USBCBErrorHandler(void)
 *******************************************************************/
void USBCBErrorHandler(void)
{
}
/*******************************************************************
 * Function:        void USBCBCheckOtherReq(void)
 *******************************************************************/
void USBCBCheckOtherReq(void)
{
        USBCheckHIDRequest();
}//end
/*******************************************************************
 * Function:        void USBCBStdSetDscHandler(void)
 *******************************************************************/
void USBCBStdSetDscHandler(void)
{
}//end
/*******************************************************************
 * Function:        void USBCBInitEP(void)
 *******************************************************************/
void USBCBInitEP(void)
{
    //enable the HID endpoint
    USBEnableEndpoint(HID_EP,USB_IN_ENABLED|USB_OUT_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
    //Re-arm the OUT endpoint for the next packet
    USBOutHandle = HIDRxPacket(HID_EP,(BYTE*)&ReceivedDataBuffer,64);
}
/*******************************************************************
 * Function:        void USBCBSendResume(void)
 ******************************************************************/
void USBCBSendResume(void)
{
    static WORD delay_count;

    if(USBGetRemoteWakeupStatus() == TRUE)
    {
        //Verify that the USB bus is in fact suspended, before we send
        //remote wakeup signalling.
        if(USBIsBusSuspended() == TRUE)
        {
            USBMaskInterrupts();

            //Clock switch to settings consistent with normal USB operation.
            USBCBWakeFromSuspend();
            USBSuspendControl = 0;
            USBBusIsSuspended = FALSE;  //So we don't execute this code again,

            delay_count = 3600U;
            do
            {
                delay_count--;
            }while(delay_count);

            //Now drive the resume K-state signalling onto the USB bus.
            USBResumeControl = 1;       // Start RESUME signaling
            delay_count = 1800U;        // Set RESUME line for 1-13 ms
            do
            {
                delay_count--;
            }while(delay_count);
            USBResumeControl = 0;       //Finished driving resume signalling

            USBUnmaskInterrupts();
        }
    }
}
/*******************************************************************
 * Function:        BOOL USER_USB_CALLBACK_EVENT_HANDLER(
 *******************************************************************/
BOOL USER_USB_CALLBACK_EVENT_HANDLER(USB_EVENT event, void *pdata, WORD size)
{
    switch(event)
    {
        case EVENT_TRANSFER:
            break;
        case EVENT_SOF:
            USBCB_SOF_Handler();
            break;
        case EVENT_SUSPEND:
            USBCBSuspend();
            break;
        case EVENT_RESUME:
            USBCBWakeFromSuspend();
            break;
        case EVENT_CONFIGURED:
            USBCBInitEP();
            break;
        case EVENT_SET_DESCRIPTOR:
            USBCBStdSetDscHandler();
            break;
        case EVENT_EP0_REQUEST:
            USBCBCheckOtherReq();
            break;
        case EVENT_BUS_ERROR:
            USBCBErrorHandler();
            break;
        case EVENT_TRANSFER_TERMINATED:

            break;
        default:
            break;
    }
    return TRUE;
}

//-------------------------------------------------------------------------------
/******************************************************************** FileName: usb_descriptors.c Dependencies: See INCLUDES section Processor: PIC18 or PIC24 USB Microcontrollers Hardware: The code is natively intended to be used on the following hardware platforms: PICDEM・FS USB Demo Board, PIC18F87J50 FS USB Plug-In Module, or Explorer 16 + PIC24 USB PIM. The firmware may be modified for use on other USB platforms by editing the HardwareProfile.h file. Complier: Microchip C18 (for PIC18) or C30 (for PIC24) Company: Microchip Technology, Inc. Software License Agreement: The software supplied herewith by Microchip Technology Incorporated (the 鼎ompany・ for its PICョ Microcontroller is intended and supplied to you, the Company痴 customer, for use solely and exclusively on Microchip PIC Microcontroller products. The software is owned by the Company and/or its supplier, and is protected under applicable copyright laws. All rights are reserved. Any use in violation of the foregoing restrictions may subject the user to criminal sanctions under applicable laws, as well as to civil liability for the breach of the terms and conditions of this license. THIS SOFTWARE IS PROVIDED IN AN 鄭S IS・CONDITION. NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. ********************************************************************* -usb_descriptors.c- ------------------------------------------------------------------- Filling in the descriptor values in the usb_descriptors.c file: ------------------------------------------------------------------- [Device Descriptors] The device descriptor is defined as a USB_DEVICE_DESCRIPTOR type. This type is defined in usb_ch9.h Each entry into this structure needs to be the correct length for the data type of the entry. [Configuration Descriptors] The configuration descriptor was changed in v2.x from a structure to a BYTE array. Given that the configuration is now a byte array each byte of multi-byte fields must be listed individually. This means that for fields like the total size of the configuration where the field is a 16-bit value "64,0," is the correct entry for a configuration that is only 64 bytes long and not "64," which is one too few bytes. The configuration attribute must always have the _DEFAULT definition at the minimum. Additional options can be ORed to the _DEFAULT attribute. Available options are _SELF and _RWU. These definitions are defined in the usb_device.h file. The _SELF tells the USB host that this device is self-powered. The _RWU tells the USB host that this device supports Remote Wakeup. [Endpoint Descriptors] Like the configuration descriptor, the endpoint descriptors were changed in v2.x of the stack from a structure to a BYTE array. As endpoint descriptors also has a field that are multi-byte entities, please be sure to specify both bytes of the field. For example, for the endpoint size an endpoint that is 64 bytes needs to have the size defined as "64,0," instead of "64," Take the following example: // Endpoint Descriptor // 0x07, //the size of this descriptor // USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor _EP02_IN, //EndpointAddress _INT, //Attributes 0x08,0x00, //size (note: 2 bytes) 0x02, //Interval The first two parameters are self-explanatory. They specify the length of this endpoint descriptor (7) and the descriptor type. The next parameter identifies the endpoint, the definitions are defined in usb_device.h and has the following naming convention: _EP<##>_<dir> where ## is the endpoint number and dir is the direction of transfer. The dir has the value of either 'OUT' or 'IN'. The next parameter identifies the type of the endpoint. Available options are _BULK, _INT, _ISO, and _CTRL. The _CTRL is not typically used because the default control transfer endpoint is not defined in the USB descriptors. When _ISO option is used, addition options can be ORed to _ISO. Example: _ISO|_AD|_FE This describes the endpoint as an isochronous pipe with adaptive and feedback attributes. See usb_device.h and the USB specification for details. The next parameter defines the size of the endpoint. The last parameter in the polling interval. ------------------------------------------------------------------- Adding a USB String ------------------------------------------------------------------- A string descriptor array should have the following format: rom struct{byte bLength;byte bDscType;word string[size];}sdxxx={ sizeof(sdxxx),DSC_STR,<text>}; The above structure provides a means for the C compiler to calculate the length of string descriptor sdxxx, where xxx is the index number. The first two bytes of the descriptor are descriptor length and type. The rest <text> are string texts which must be in the unicode format. The unicode format is achieved by declaring each character as a word type. The whole text string is declared as a word array with the number of characters equals to <size>. <size> has to be manually counted and entered into the array declaration. Let's study this through an example: if the string is "USB" , then the string descriptor should be: (Using index 02) rom struct{byte bLength;byte bDscType;word string[3];}sd002={ sizeof(sd002),DSC_STR,'U','S','B'}; A USB project may have multiple strings and the firmware supports the management of multiple strings through a look-up table. The look-up table is defined as: rom const unsigned char *rom USB_SD_Ptr[]={&sd000,&sd001,&sd002}; The above declaration has 3 strings, sd000, sd001, and sd002. Strings can be removed or added. sd000 is a specialized string descriptor. It defines the language code, usually this is US English (0x0409). The index of the string must match the index position of the USB_SD_Ptr array, &sd000 must be in position USB_SD_Ptr[0], &sd001 must be in position USB_SD_Ptr[1] and so on. The look-up table USB_SD_Ptr is used by the get string handler function. ------------------------------------------------------------------- The look-up table scheme also applies to the configuration descriptor. A USB device may have multiple configuration descriptors, i.e. CFG01, CFG02, etc. To add a configuration descriptor, user must implement a structure similar to CFG01. The next step is to add the configuration descriptor name, i.e. cfg01, cfg02,.., to the look-up table USB_CD_Ptr. USB_CD_Ptr[0] is a dummy place holder since configuration 0 is the un-configured state according to the definition in the USB specification. ********************************************************************/ /********************************************************************* * Descriptor specific type definitions are defined in: * usb_device.h * * Configuration options are defined in: * usb_config.h ********************************************************************/ #ifndef __USB_DESCRIPTORS_C #define __USB_DESCRIPTORS_C /** INCLUDES *******************************************************/ #include "usb.h" #include "usb_function_hid.h" /** CONSTANTS ******************************************************/ #if defined(__18CXX) #pragma romdata #endif /* Device Descriptor */ ROM USB_DEVICE_DESCRIPTOR device_dsc= //デバイスデスクリプタ { 0x12, // Size of this descriptor in bytes USB_DESCRIPTOR_DEVICE, // DEVICE descriptor type 0x0200, // USB Spec Release Number in BCD format 0x00, // Class Code //HIDクラス 0x00, // Subclass code //未定義(=汎用) 0x00, // Protocol code USB_EP0_BUFF_SIZE, // Max packet size for EP0, see usb_config.h 0x04D8, // Vendor ID //ベンダーID 0x003F, // Product ID: Custom HID demo //プロダクトID 0x0002, // Device release number in BCD format 0x01, // Manufacturer string index 0x02, // Product string index 0x00, // Device serial number string index 0x01 // Number of possible configurations }; /* Configuration 1 Descriptor */ ROM BYTE configDescriptor1[]={ //コンフィグデスクリプタ /* Configuration Descriptor */ 0x09, //sizeof(USB_CFG_DSC), // Size of this descriptor in bytes USB_DESCRIPTOR_CONFIGURATION, // CONFIGURATION descriptor type 0x29,0x00, // Total length of data for this cfg 1, // Number of interfaces in this cfg 1, // Index value of this configuration 0, // Configuration string index _DEFAULT | _SELF, // Attributes, see usb_device.h 50, // Max power consumption (2X mA) //最大消費電流50mA /* Interface Descriptor */ //インターフェースデスクリプタ 0x09, //sizeof(USB_INTF_DSC), // Size of this descriptor in bytes USB_DESCRIPTOR_INTERFACE, // INTERFACE descriptor type 0, // Interface Number 0, // Alternate Setting Number 2, // Number of endpoints in this intf //エンドポイントの数 HID_INTF, // Class code 0, // Subclass code 0, // Protocol code 0, // Interface string index /* HID Class-Specific Descriptor *///HIDクラスの仕様に係るデスクリプタ部分 0x09, //sizeof(USB_HID_DSC)+3, // Size of this descriptor in bytes DSC_HID, // HID descriptor type 0x11,0x01, // HID Spec Release Number in BCD format (1.11) 0x00, // Country Code (0x00 for Not supported) HID_NUM_OF_DSC, // Number of class descriptors, see usbcfg.h DSC_RPT, // Report descriptor type HID_RPT01_SIZE,0x00, //sizeof(hid_rpt01), // Size of the report descriptor /* Endpoint Descriptor */ // エンドポイントデスクリプタ 0x07, /*sizeof(USB_EP_DSC)*/ USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor HID_EP | _EP_IN, //EndpointAddress _INTERRUPT, //Attributes 0x40,0x00, //size 0x01, //Interval /* Endpoint Descriptor */ 0x07, /*sizeof(USB_EP_DSC)*/ USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor HID_EP | _EP_OUT, //EndpointAddress _INTERRUPT, //Attributes 0x40,0x00, //size 0x01 //Interval }; //Language code string descriptor ROM struct{BYTE bLength;BYTE bDscType;WORD string[1];}sd000={ sizeof(sd000),USB_DESCRIPTOR_STRING,{0x0409 }}; //Manufacturer string descriptor ROM struct{BYTE bLength;BYTE bDscType;WORD string[25];}sd001={ sizeof(sd001),USB_DESCRIPTOR_STRING, {'M','i','c','r','o','c','h','i','p',' ', 'T','e','c','h','n','o','l','o','g','y',' ','I','n','c','.' }}; //Product string descriptor ROM struct{BYTE bLength;BYTE bDscType;WORD string[22];}sd002={ sizeof(sd002),USB_DESCRIPTOR_STRING, {'S','i','m','p','l','e',' ','H','I','D',' ', 'D','e','v','i','c','e',' ','D','e','m','o' }}; //Class specific descriptor - HID ROM struct{BYTE report[HID_RPT01_SIZE];}hid_rpt01={ { 0x06, 0x00, 0xFF, // Usage Page = 0xFF00 (Vendor Defined Page 1) 0x09, 0x01, // Usage (Vendor Usage 1) 0xA1, 0x01, // Collection (Application) 0x19, 0x01, // Usage Minimum 0x29, 0x40, // Usage Maximum //64 input usages total (0x01 to 0x40) 0x15, 0x01, // Logical Minimum (data bytes in the report may have minimum value = 0x00) 0x25, 0x40, // Logical Maximum (data bytes in the report may have maximum value = 0x00FF = unsigned 255) 0x75, 0x08, // Report Size: 8-bit field size 0x95, 0x40, // Report Count: Make sixty-four 8-bit fields (the next time the parser hits an "Input", "Output", or "Feature" item) 0x81, 0x00, // Input (Data, Array, Abs): Instantiates input packet fields based on the above report size, count, logical min/max, and usage. 0x19, 0x01, // Usage Minimum 0x29, 0x40, // Usage Maximum //64 output usages total (0x01 to 0x40) 0x91, 0x00, // Output (Data, Array, Abs): Instantiates output packet fields. Uses same report size and count as "Input" fields, since nothing new/different was specified to the parser since the "Input" item. 0xC0} // End Collection }; //Array of configuration descriptors ROM BYTE *ROM USB_CD_Ptr[]= { (ROM BYTE *ROM)&configDescriptor1 }; //Array of string descriptors ROM BYTE *ROM USB_SD_Ptr[]= { (ROM BYTE *ROM)&sd000, (ROM BYTE *ROM)&sd001, (ROM BYTE *ROM)&sd002 }; /** EOF usb_descriptors.c ***************************************************/ #endif

 

<実行結果>

 接続ボタンをクリックした後、LED0、LED2、LED3を点灯させたところです。
尚、PIC18F14K50のキバン上には本テーマと関係ない部品が多々搭載されています。



 PIC18F14K50 HIDクラス スイッチの状態&電圧 読込・表示
  
<試作品仕様>
 ・PCとPIC間のUSB通信はHIDクラスとする。
 ・PIC18F14K50のキバン上のスイッチ×3個を押すと PC(Windows)上の対応するovalShape×3個の色が 灰色→オレンジ色に変わること
 ・PCとPIC間のUSB通信はHIDクラスとする。
 ・可変抵抗器×3個により設定される電圧をPIC18F14K50の内蔵ADコンバータで読込、この電圧値[V]をPC上の対応するテキストボックス×3個に表示のこと。
 ・テキストボックスに表示される電圧[V]は、小数点以下2桁とする。
 ・USB通信ONのボタンボタンスイッチをフォーム上にもうけること。 またUSB通信が確立したら”接続完了!”の文字をテキストボックスに表示のこと

 ★ PCのソフト(VC++)は こちらを参照願います

<試作品回路図>(→回路図のPDFファイル) 

          




<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています








   <プログラム例>

//
//USB HIDクラス

#include "usb.h"
#include "HardwareProfile.h"
#include "usb_function_hid.h"
/** コンフィギュレーション ***********************/
#pragma config CPUDIV = NOCLKDIV ,USBDIV = OFF, PCLKEN = ON
#pragma config FOSC = HS, PLLEN = ON, HFOFST = OFF
#pragma config PWRTEN = ON, BOREN = OFF, MCLRE = OFF, BORV = 30
#pragma config WDTEN = OFF, LVP = OFF, FCMEN = OFF, IESO = OFF
#pragma config CP0 = OFF, XINST = OFF
/******** USB関連バッファ、変数定義 ****/
#pragma udata usbram2
unsigned char ReceivedDataBuffer[64];
unsigned char SendBuf[64];
#pragma udata
USB_HANDLE USBOutHandle = 0;
USB_HANDLE USBInHandle = 0;
BOOL blinkStatusValid = TRUE;
/**** グローバル変数定義 ***/
BYTE  counter;
BOOL  blinkStatusValid;
/*** コマンド定数定義 ***/
typedef enum
{
    CHECK       = 0x30,
    POUT        = 0x31,
    PIN         = 0x32,
    AIN         = 0x33,
    RESET       = 0xFF

}TYPE_CMD;


void BlinkUSBStatus(void);
void ProcessIO(void);
void YourHighPriorityISRCode();
void YourLowPriorityISRCode();
void USBCBSendResume(void);

//割り込みベクタ定義
#pragma code REMAPPED_HIGH_INTERRUPT_VECTOR = 0x08
void Remapped_High_ISR (void)
{
     _asm goto YourHighPriorityISRCode _endasm
}
#pragma code REMAPPED_LOW_INTERRUPT_VECTOR = 0x18
void Remapped_Low_ISR (void)
{
     _asm goto YourLowPriorityISRCode _endasm
}

//割り込み処理関数
#pragma code
#pragma interrupt YourHighPriorityISRCode
void YourHighPriorityISRCode()
{
        USBDeviceTasks();
}
#pragma interruptlow YourLowPriorityISRCode
void YourLowPriorityISRCode()
{
}


#pragma code
void main(void)
{
        
        ANSEL = 0x00;                                   // デジタルに設定
        ANSELH =0x07;                                   // AN8,9,10のみアナログ
        TRISA = 0xFF;                                   // RA0-5入力
        TRISB = 0x7F;                                   // RB7(TX)以外すべて入力
        LATC = 0;                                               // 出力初期化
        TRISC = 0xF0;                                   // RC6,7アナログ入力、RC0-3出力
        
        // ADC初期化
        ADCON0 = 0;                                             // 停止
        ADCON1 = 0;                                             // VDD-Vss
        ADCON2 = 0xBE;                                  // 右詰め,20Tad,Fosc/64
        //USB関連
        USBDeviceInit();                                // USB初期化
        USBInHandle = 0;
        USBOutHandle = 0;
        blinkStatusValid = TRUE;                // USB目印LED有効化
        USBDeviceAttach();                              // USB割り込み有効化


        
    while(1)
    {
                //USB接続中なら送受信実行
                if((USBDeviceState >= CONFIGURED_STATE)&&(USBSuspendControl!=1))
                        ProcessIO();                            // コマンド実行
        }
}

 //ユーザーアプリの入出力処理関数
void ProcessIO(void)
{
        //データ受信処理
        if(!HIDRxHandleBusy(USBOutHandle))
        {
                blinkStatusValid = FALSE;
                SendBuf[0] = ReceivedDataBuffer[0];
                SendBuf[1] = ReceivedDataBuffer[1];


                switch(ReceivedDataBuffer[0])           // コマンドコードチェック
                {
                        //接続確認応答
                        case CHECK:
                                SendBuf[2] = 'O';
                                SendBuf[3] = 'K';
                                if(!HIDTxHandleBusy(USBInHandle))
                                        USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&SendBuf[0],64);
                                break;
                        //入力ピン状態要求と応答の場合
                        case PIN :
                                if(ReceivedDataBuffer[1] == 0x31){
                                        if(sw1)
                                                SendBuf[2] = 0x31;
                                        else
                                                SendBuf[2] = 0x30;
                                }
                                else if(ReceivedDataBuffer[1] == 0x32){
                                        if(sw2)
                                                SendBuf[2] = 0x31;
                                        else
                                                SendBuf[2] = 0x30;
                                }
                                else if(ReceivedDataBuffer[1] == 0x33){
                                        if(sw3)
                                                SendBuf[2] = 0x31;
                                        else
                                                SendBuf[2] = 0x30;
                                }
                                if(!HIDTxHandleBusy(USBInHandle))
                                        USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&SendBuf[0],64);
                                break;
                        /***** アナログ入力要求と応答 *****/
                        case AIN:
                                /* チャネル選択後A/D変換 AN8,AN9, An10 */
                                ADCON0 = ((ReceivedDataBuffer[1]-0x31+8) << 2) + 0x01;
                                ADCON0bits.GO = 1;                      // A/D変換開始
                                while(ADCON0bits.NOT_DONE);             // 変換完了待ち
                                SendBuf[2] = ADRESL;            // 送信バッファにセット
                                SendBuf[3] = ADRESH;
                                if(!HIDTxHandleBusy(USBInHandle))
                                        USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&SendBuf[0],64);
                                break;
                        
                        default:
                                break;
                }
                // 次の受信実行
                USBOutHandle = HIDRxPacket(HID_EP,(BYTE*)&ReceivedDataBuffer,64);
        }
}
/******************************************************************
************** USB Callback Functions *****************************
*******************************************************************/
/******************************************************************
 * Function:        void USBCBSuspend(void)
 ******************************************************************/
void USBCBSuspend(void)
{
}
/*******************************************************************
 * Function:        void USBCBWakeFromSuspend(void)
 *******************************************************************/
void USBCBWakeFromSuspend(void)
{
}
/********************************************************************
 * Function:        void USBCB_SOF_Handler(void)
 *******************************************************************/
void USBCB_SOF_Handler(void)
{
}
/*******************************************************************
 * Function:        void USBCBErrorHandler(void)
 *******************************************************************/
void USBCBErrorHandler(void)
{
}
/*******************************************************************
 * Function:        void USBCBCheckOtherReq(void)
 *******************************************************************/
void USBCBCheckOtherReq(void)
{
        USBCheckHIDRequest();
}//end
/*******************************************************************
 * Function:        void USBCBStdSetDscHandler(void)
 *******************************************************************/
void USBCBStdSetDscHandler(void)
{
}//end
/*******************************************************************
 * Function:        void USBCBInitEP(void)
 *******************************************************************/
void USBCBInitEP(void)
{
    //enable the HID endpoint
    USBEnableEndpoint(HID_EP,USB_IN_ENABLED|USB_OUT_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
    //Re-arm the OUT endpoint for the next packet
    USBOutHandle = HIDRxPacket(HID_EP,(BYTE*)&ReceivedDataBuffer,64);
}
/*******************************************************************
 * Function:        void USBCBSendResume(void)
 ******************************************************************/
void USBCBSendResume(void)
{
    static WORD delay_count;

    if(USBGetRemoteWakeupStatus() == TRUE)
    {
        //Verify that the USB bus is in fact suspended, before we send
        //remote wakeup signalling.
        if(USBIsBusSuspended() == TRUE)
        {
            USBMaskInterrupts();

            //Clock switch to settings consistent with normal USB operation.
            USBCBWakeFromSuspend();
            USBSuspendControl = 0;
            USBBusIsSuspended = FALSE;  //So we don't execute this code again,

            delay_count = 3600U;
            do
            {
                delay_count--;
            }while(delay_count);

            //Now drive the resume K-state signalling onto the USB bus.
            USBResumeControl = 1;       // Start RESUME signaling
            delay_count = 1800U;        // Set RESUME line for 1-13 ms
            do
            {
                delay_count--;
            }while(delay_count);
            USBResumeControl = 0;       //Finished driving resume signalling

            USBUnmaskInterrupts();
        }
    }
}
/*******************************************************************
 * Function:        BOOL USER_USB_CALLBACK_EVENT_HANDLER(
 *******************************************************************/
BOOL USER_USB_CALLBACK_EVENT_HANDLER(USB_EVENT event, void *pdata, WORD size)
{
    switch(event)
    {
        case EVENT_TRANSFER:
            break;
        case EVENT_SOF:
            USBCB_SOF_Handler();
            break;
        case EVENT_SUSPEND:
            USBCBSuspend();
            break;
        case EVENT_RESUME:
            USBCBWakeFromSuspend();
            break;
        case EVENT_CONFIGURED:
            USBCBInitEP();
            break;
        case EVENT_SET_DESCRIPTOR:
            USBCBStdSetDscHandler();
            break;
        case EVENT_EP0_REQUEST:
            USBCBCheckOtherReq();
            break;
        case EVENT_BUS_ERROR:
            USBCBErrorHandler();
            break;
        case EVENT_TRANSFER_TERMINATED:

            break;
        default:
            break;
    }
    return TRUE;
}


//----------------------------------------------------

/********************************************************************
 FileName:      usb_descriptors.c
 Dependencies:  See INCLUDES section
 Processor:             PIC18 or PIC24 USB Microcontrollers
 Hardware:              The code is natively intended to be used on the following
                                hardware platforms: PICDEM・FS USB Demo Board, 
                                PIC18F87J50 FS USB Plug-In Module, or
                                Explorer 16 + PIC24 USB PIM.  The firmware may be
                                modified for use on other USB platforms by editing the
                                HardwareProfile.h file.
 Complier:      Microchip C18 (for PIC18) or C30 (for PIC24)
 Company:               Microchip Technology, Inc.

 Software License Agreement:

 The software supplied herewith by Microchip Technology Incorporated
 (the 鼎ompany・ for its PICョ Microcontroller is intended and
 supplied to you, the Company痴 customer, for use solely and
 exclusively on Microchip PIC Microcontroller products. The
 software is owned by the Company and/or its supplier, and is
 protected under applicable copyright laws. All rights are reserved.
 Any use in violation of the foregoing restrictions may subject the
 user to criminal sanctions under applicable laws, as well as to
 civil liability for the breach of the terms and conditions of this
 license.

 THIS SOFTWARE IS PROVIDED IN AN 鄭S IS・CONDITION. NO WARRANTIES,
 WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
 TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
 IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
 CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.

*********************************************************************
-usb_descriptors.c-
-------------------------------------------------------------------
Filling in the descriptor values in the usb_descriptors.c file:
-------------------------------------------------------------------

[Device Descriptors]
The device descriptor is defined as a USB_DEVICE_DESCRIPTOR type.  
This type is defined in usb_ch9.h  Each entry into this structure
needs to be the correct length for the data type of the entry.

[Configuration Descriptors]
The configuration descriptor was changed in v2.x from a structure
to a BYTE array.  Given that the configuration is now a byte array
each byte of multi-byte fields must be listed individually.  This
means that for fields like the total size of the configuration where
the field is a 16-bit value "64,0," is the correct entry for a
configuration that is only 64 bytes long and not "64," which is one
too few bytes.

The configuration attribute must always have the _DEFAULT
definition at the minimum. Additional options can be ORed
to the _DEFAULT attribute. Available options are _SELF and _RWU.
These definitions are defined in the usb_device.h file. The
_SELF tells the USB host that this device is self-powered. The
_RWU tells the USB host that this device supports Remote Wakeup.

[Endpoint Descriptors]
Like the configuration descriptor, the endpoint descriptors were 
changed in v2.x of the stack from a structure to a BYTE array.  As
endpoint descriptors also has a field that are multi-byte entities,
please be sure to specify both bytes of the field.  For example, for
the endpoint size an endpoint that is 64 bytes needs to have the size
defined as "64,0," instead of "64,"

Take the following example:
    // Endpoint Descriptor //
    0x07,                       //the size of this descriptor //
    USB_DESCRIPTOR_ENDPOINT,    //Endpoint Descriptor
    _EP02_IN,                   //EndpointAddress
    _INT,                       //Attributes
    0x08,0x00,                  //size (note: 2 bytes)
    0x02,                       //Interval

The first two parameters are self-explanatory. They specify the
length of this endpoint descriptor (7) and the descriptor type.
The next parameter identifies the endpoint, the definitions are
defined in usb_device.h and has the following naming
convention:
_EP<##>_<dir>
where ## is the endpoint number and dir is the direction of
transfer. The dir has the value of either 'OUT' or 'IN'.
The next parameter identifies the type of the endpoint. Available
options are _BULK, _INT, _ISO, and _CTRL. The _CTRL is not
typically used because the default control transfer endpoint is
not defined in the USB descriptors. When _ISO option is used,
addition options can be ORed to _ISO. Example:
_ISO|_AD|_FE
This describes the endpoint as an isochronous pipe with adaptive
and feedback attributes. See usb_device.h and the USB
specification for details. The next parameter defines the size of
the endpoint. The last parameter in the polling interval.

-------------------------------------------------------------------
Adding a USB String
-------------------------------------------------------------------
A string descriptor array should have the following format:

rom struct{byte bLength;byte bDscType;word string[size];}sdxxx={
sizeof(sdxxx),DSC_STR,<text>};

The above structure provides a means for the C compiler to
calculate the length of string descriptor sdxxx, where xxx is the
index number. The first two bytes of the descriptor are descriptor
length and type. The rest <text> are string texts which must be
in the unicode format. The unicode format is achieved by declaring
each character as a word type. The whole text string is declared
as a word array with the number of characters equals to <size>.
<size> has to be manually counted and entered into the array
declaration. Let's study this through an example:
if the string is "USB" , then the string descriptor should be:
(Using index 02)
rom struct{byte bLength;byte bDscType;word string[3];}sd002={
sizeof(sd002),DSC_STR,'U','S','B'};

A USB project may have multiple strings and the firmware supports
the management of multiple strings through a look-up table.
The look-up table is defined as:
rom const unsigned char *rom USB_SD_Ptr[]={&sd000,&sd001,&sd002};

The above declaration has 3 strings, sd000, sd001, and sd002.
Strings can be removed or added. sd000 is a specialized string
descriptor. It defines the language code, usually this is
US English (0x0409). The index of the string must match the index
position of the USB_SD_Ptr array, &sd000 must be in position
USB_SD_Ptr[0], &sd001 must be in position USB_SD_Ptr[1] and so on.
The look-up table USB_SD_Ptr is used by the get string handler
function.

-------------------------------------------------------------------

The look-up table scheme also applies to the configuration
descriptor. A USB device may have multiple configuration
descriptors, i.e. CFG01, CFG02, etc. To add a configuration
descriptor, user must implement a structure similar to CFG01.
The next step is to add the configuration descriptor name, i.e.
cfg01, cfg02,.., to the look-up table USB_CD_Ptr. USB_CD_Ptr[0]
is a dummy place holder since configuration 0 is the un-configured
state according to the definition in the USB specification.

********************************************************************/
 
/*********************************************************************
 * Descriptor specific type definitions are defined in:
 * usb_device.h
 *
 * Configuration options are defined in:
 * usb_config.h
 ********************************************************************/
#ifndef __USB_DESCRIPTORS_C
#define __USB_DESCRIPTORS_C

/** INCLUDES *******************************************************/
#include "usb.h"
#include "usb_function_hid.h"

/** CONSTANTS ******************************************************/
#if defined(__18CXX)
#pragma romdata
#endif

/* Device Descriptor */
ROM USB_DEVICE_DESCRIPTOR device_dsc=
{
    0x12,       // Size of this descriptor in bytes
    USB_DESCRIPTOR_DEVICE,  // DEVICE descriptor type
    0x0200,                 // USB Spec Release Number in BCD format
    0x00,                   // Class Code
    0x00,                   // Subclass code
    0x00,                   // Protocol code
    USB_EP0_BUFF_SIZE,          // Max packet size for EP0, see usb_config.h
    0x04D8,                 // Vendor ID
    0x003F,                 // Product ID: Custom HID demo
    0x0002,                 // Device release number in BCD format
    0x01,                   // Manufacturer string index
    0x02,                   // Product string index
    0x00,                   // Device serial number string index
    0x01                    // Number of possible configurations
};

/* Configuration 1 Descriptor */
ROM BYTE configDescriptor1[]={
    /* Configuration Descriptor */
    0x09,       //sizeof(USB_CFG_DSC),  // Size of this descriptor in bytes
    USB_DESCRIPTOR_CONFIGURATION,       // CONFIGURATION descriptor type
    0x29,0x00,                  // Total length of data for this cfg
    1,                      // Number of interfaces in this cfg
    1,                      // Index value of this configuration
    0,                      // Configuration string index
    _DEFAULT | _SELF,       // Attributes, see usb_device.h
    50,                     // Max power consumption (2X mA)
                                                        
    /* Interface Descriptor */
    0x09,       //sizeof(USB_INTF_DSC), // Size of this descriptor in bytes
    USB_DESCRIPTOR_INTERFACE,           // INTERFACE descriptor type
    0,                      // Interface Number
    0,                      // Alternate Setting Number
    2,                      // Number of endpoints in this intf
    HID_INTF,               // Class code
    0,                                          // Subclass code
    0,                                          // Protocol code
    0,                      // Interface string index

    /* HID Class-Specific Descriptor */
    0x09,       //sizeof(USB_HID_DSC)+3, // Size of this descriptor in bytes
    DSC_HID,                // HID descriptor type
    0x11,0x01,              // HID Spec Release Number in BCD format (1.11)
    0x00,                   // Country Code (0x00 for Not supported)
    HID_NUM_OF_DSC,         // Number of class descriptors, see usbcfg.h
    DSC_RPT,                // Report descriptor type
    HID_RPT01_SIZE,0x00,        //sizeof(hid_rpt01),  // Size of the report descriptor
    
    /* Endpoint Descriptor */
    0x07,       /*sizeof(USB_EP_DSC)*/
    USB_DESCRIPTOR_ENDPOINT,            //Endpoint Descriptor
    HID_EP | _EP_IN,            //EndpointAddress
    _INTERRUPT,             //Attributes
    0x40,0x00,              //size
    0x01,                   //Interval

    /* Endpoint Descriptor */
    0x07,       /*sizeof(USB_EP_DSC)*/
    USB_DESCRIPTOR_ENDPOINT,            //Endpoint Descriptor
    HID_EP | _EP_OUT,       //EndpointAddress
    _INTERRUPT,             //Attributes
    0x40,0x00,              //size
    0x01                    //Interval
};

//Language code string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[1];}sd000={
sizeof(sd000),USB_DESCRIPTOR_STRING,{0x0409
}};

//Manufacturer string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[25];}sd001={
sizeof(sd001),USB_DESCRIPTOR_STRING,
{'M','i','c','r','o','c','h','i','p',' ',
'T','e','c','h','n','o','l','o','g','y',' ','I','n','c','.'
}};

//Product string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[22];}sd002={
sizeof(sd002),USB_DESCRIPTOR_STRING,
{'S','i','m','p','l','e',' ','H','I','D',' ',
'D','e','v','i','c','e',' ','D','e','m','o'
}};

//Class specific descriptor - HID 
ROM struct{BYTE report[HID_RPT01_SIZE];}hid_rpt01={
{
    0x06, 0x00, 0xFF,       // Usage Page = 0xFF00 (Vendor Defined Page 1)
    0x09, 0x01,             // Usage (Vendor Usage 1)
    0xA1, 0x01,             // Collection (Application)
    0x19, 0x01,             // Usage Minimum 
    0x29, 0x40,             // Usage Maximum    //64 input usages total (0x01 to 0x40)
    0x15, 0x01,             // Logical Minimum (data bytes in the report may have minimum value = 0x00)
    0x25, 0x40,                 // Logical Maximum (data bytes in the report may have maximum value = 0x00FF = unsigned 255)
    0x75, 0x08,             // Report Size: 8-bit field size
    0x95, 0x40,             // Report Count: Make sixty-four 8-bit fields (the next time the parser hits an "Input", "Output", or "Feature" item)
    0x81, 0x00,             // Input (Data, Array, Abs): Instantiates input packet fields based on the above report size, count, logical min/max, and usage.
    0x19, 0x01,             // Usage Minimum 
    0x29, 0x40,             // Usage Maximum    //64 output usages total (0x01 to 0x40)
    0x91, 0x00,             // Output (Data, Array, Abs): Instantiates output packet fields.  Uses same report size and count as "Input" fields, since nothing new/different was specified to the parser since the "Input" item.
    0xC0}                   // End Collection
};                  


//Array of configuration descriptors
ROM BYTE *ROM USB_CD_Ptr[]=
{
    (ROM BYTE *ROM)&configDescriptor1
};

//Array of string descriptors
ROM BYTE *ROM USB_SD_Ptr[]=
{
    (ROM BYTE *ROM)&sd000,
    (ROM BYTE *ROM)&sd001,
    (ROM BYTE *ROM)&sd002
};

/** EOF usb_descriptors.c ***************************************************/

#endif





<実行結果>
 ・接続ボタンをクリックしてUSB接続をした後に スイッチボタンSW1とSW3を押した時のPCのフォーム画面です。
 ・ovalShapeがオレンジ色になっているスイッチはON状態をあらわし、灰色はOFF状態の場合です。
 ・テキストボックスに表示されている値は、PIC18F14K50が読み込んだ電圧値で、小数点以下2桁で表示されています。
 ・PIC18F14K50のキバン上のスイッチ×3個を押すと PC(Windows)上の対応するovalShape×3個の色が 灰色→オレンジ色に変わること
 ・PCとPIC間のUSB通信はHIDクラスとする。
 ・可変抵抗器×3個により設定される電圧をPIC18F14K50内蔵ADコンバータで読込、この電圧値[V]をPC上の対応するテキストボックス×3個に表示のこと。
 ・テキストボックスに表示される電圧[V]は、小数点以下2桁とする。
 ・USB通信ONのボタンボタンスイッチをフォーム上にもうけること。 またUSB通信が確立したら”接続完了!”の文字をテキストボックスに表示のこと
  






■ PIC32MX795F512L HIDクラス LED点灯/消灯、ADコンバータ読込・表示
<試作品仕様>
  ・PCとPIC間のUSB通信はHIDクラスとする。
  ・PC(Windows)上のボタンスイッチ×4個をクリックすると PIC32MX795F512Lのキバン上の対応するLEDがON/OFFすること
  ・PCとPIC間のUSB通信はHIDクラスとする。
  ・ボタンスイッチはLEDがONしているときは赤色、OFFの時は灰色とする。
  ・USB通信ONのボタンボタンスイッチをフォーム上にもうけること。 またUSB通信が確立したら”接続完了!”の文字をテキストボックスに表示のこと
  ・PIC32MX795F512Lのキバン上のスイッチ×3個を押すと PC(Windows)上の対応するovalShape×3個の色が 灰色→オレンジ色に変わること
  ・可変抵抗器により設定される電圧をPIC32MX795F512L内蔵ADコンバータで読込、この電圧値[V]をPC上のテキストボックスに表示のこと。
  ・テキストボックスに表示される電圧[V]は、小数点以下2桁とする。
  ・USB通信ONのボタンボタンスイッチをフォーム上にもうけること。 またUSB通信が確立したら”接続完了!”の文字をテキストボックスに表示のこと

 ★ PC側のソフト(Windows)は こちらを参照願います 
   
<試作品回路図>(→回路図のPDFファイル







<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています







   <プログラム例>
//main.c        //32MX795

#include "./USB/usb.h"
#include "HardwareProfile.h"
#include "./USB/usb_function_hid.h"

//システムクロック80MHz  ペリフェラルクロック80MHz
        #pragma config UPLLEN   = ON        // USB PLL Enabled
        #pragma config FPLLMUL  = MUL_20        // PLL Multiplier
        #pragma config UPLLIDIV = DIV_2         // USB PLL Input Divider
        #pragma config FPLLIDIV = DIV_2         // PLL Input Divider
        #pragma config FPLLODIV = DIV_1         // PLL Output Divider
        #pragma config FPBDIV   = DIV_1         // Peripheral Clock divisor
        #pragma config FWDTEN   = OFF           // Watchdog Timer
        #pragma config WDTPS    = PS1           // Watchdog Timer Postscale
        #pragma config FCKSM    = CSDCMD        // Clock Switching & Fail Safe Clock Monitor
        #pragma config OSCIOFNC = OFF           // CLKO Enable
        #pragma config POSCMOD  = HS            // Primary Oscillator
        #pragma config IESO     = OFF           // Internal/External Switch-over
        #pragma config FSOSCEN  = OFF           // Secondary Oscillator Enable (KLO was off)
        #pragma config FNOSC    = PRIPLL        // Oscillator Selection
        #pragma config CP       = OFF           // Code Protect
        #pragma config BWP      = OFF           // Boot Flash Write Protect
        #pragma config PWP      = OFF           // Program Flash Write Protect
        #pragma config ICESEL   = ICS_PGx2      // ICE/ICD Comm Channel Select


    #define RX_DATA_BUFFER_ADDRESS
    #define TX_DATA_BUFFER_ADDRESS

unsigned char ReceivedDataBuffer[64] RX_DATA_BUFFER_ADDRESS;
unsigned char ToSendDataBuffer[64] TX_DATA_BUFFER_ADDRESS;
unsigned char SendBuf[64];


USB_HANDLE USBOutHandle = 0;    //USB handle.  Must be initialized to 0 at startup.
USB_HANDLE USBInHandle = 0;     //USB handle.  Must be initialized to 0 at startup.
BOOL blinkStatusValid = TRUE;


void BlinkUSBStatus(void);
void ProcessIO(void);
void YourHighPriorityISRCode();
void YourLowPriorityISRCode();
void USBCBSendResume(void);
WORD_VAL ReadPOT(void);

 unsigned int AdcValue;


int main(void)
{
    SYSTEMConfigPerformance(80000000);  //システム最適化


    DDPCONbits.JTAGEN = 0;  //JTAG無効化

    AD1PCFG = 0xFFFF;   //全RBポートデジタルピンとして使用
    AD1PCFGbits.PCFG9 = 0;  //AN9:アナログ
    TRISBbits.TRISB9 = 1;

    TRISAbits.TRISA2 = 0;
    TRISAbits.TRISA3 = 0;
    TRISAbits.TRISA4 = 0;
    TRISAbits.TRISA5 = 0;

    LATAbits.LATA2 = 0;
    LATAbits.LATA3 = 0;
    LATAbits.LATA4 = 0;
    LATAbits.LATA5 = 0;

    TRISDbits.TRISD6=1;
    TRISDbits.TRISD7=1;
    TRISDbits.TRISD13=1;

        //AD1CON1レジスタの設定
        AD1CON1bits.ON = 1;             //A/Dコンバータモジュール有効
   //   AD1CON1bits.FRZ = 0;    //デバッグモードに於いても動作継続
        AD1CON1bits.SIDL = 0; //アイドルモード中もモジュール動作継続
        AD1CON1bits.FORM2 = 0;  //AD1CON1bits.FORM2-AD1CON1bits.FORM0のセットで出力データ形式指定 → 000:16ビット符号なし整数形式
        AD1CON1bits.FORM1 = 0;  //011:符号付固定16ビット小数 010:固定小数16ビット 001:符号付き整数16ビット 000:16ビット符号なし整数
        AD1CON1bits.FORM0 = 0;  //111:符号付32ビット固定小数 110:32ビット固定小数 101:符号付32ビット整数 100=32ビット符号なし整数
                                //★ Michrochip データシートDS61104 では000、100がIntegerとなっているがUnsigned Integerの誤植である。 
        AD1CON1bits.SSRC2 = 1;  //AD1CON1bits.SSRC2-AD1CON1bits.SSRC0 のセットでトリガーソースを指定
        AD1CON1bits.SSRC1 = 1;  //111: 内蔵カウンタでサンプリングを終了させ変換を開始する
        AD1CON1bits.SSRC0 = 1;  //(参考)000: SAMPビットでサンプリングを終了し変換を開始する
        AD1CON1bits.CLRASAM = 0;//AD変換割り込み時の変換停止 0:次の変換値でオーバーライト
        AD1CON1bits.ASAM = 0;   //SAMPビットのセットでサンプリングを開始する。(参考)1: 自動開始(前の変換終了後すぐサンプリングを開始する)
        AD1CON1bits.SAMP = 0;   //サンプリング停止



        //AD1CON2レジスタの設定
        AD1CON2bits.VCFG2 = 0;  //リファレンス選択//AD1CON2bits.VCFG2 - AD1CON2bits.VCFG0(VCFG<2:0>)の3ビットでセット
        AD1CON2bits.VCFG1 = 0;  //★000:リファレンス電圧 → Vdd -Vss
        AD1CON2bits.VCFG0 = 0;  //(参考)001:リファレンス電圧 → 外部入力 - Vss 他
        AD1CON2bits.OFFCAL = 0; //較正モード設定 0:サンプルホールドアンプSHAの入力はAD1CHSレジスタとAD1CSSLレジスタで制御される
        AD1CON2bits.CSCNA = 1;  //★マルチプレクサMUXAでのスキャン: する
        AD1CON2bits.SMPI3 = 0;  //割り込みタイミング AD1CON2bits.SMPI3 - AD1CON2bits.SMPI0(SMPI<3:0>)の4ビットでセット
        AD1CON2bits.SMPI2 = 0;  //0000: AD変換完了毎の割り込み発生(割り込み有効の場合)
        AD1CON2bits.SMPI1 = 0;  //(参考)0011: 4サンプルのAD変換終了後       割り込み発生(割り込み有効の場合)
        AD1CON2bits.SMPI0 = 0;  //
        AD1CON2bits.BUFM = 0;   //バッファーを1個の16ワードバッファとする。 (参考)1: 2組の8ワードバッファーとする
        AD1CON2bits.ALTS = 0;   //常にMUXAを入力マルチプレクサにする (参考)1: MUXA,MUXBを交互につかう

 //AD1CON3レジスタの設定
        AD1CON3bits.ADRC = 0;   //AD変換クロック源選択//0: PBCLK(Peripheral Bus Clock) (参考)1: A/D内臓RCクロック
        AD1CON3bits.SAMC4 = 1;  //AD1CON3bits.SAMC4 - AD1CON3bits.SAMC0(SAMC<4:0>)の5ビットでセット
        AD1CON3bits.SAMC3 = 1;  //アクイジションタイム(Tad(クロック周期)×N)設定(ホールドキャパシタ充電所要時間)
        AD1CON3bits.SAMC2 = 1;  //1111: 31Tad
        AD1CON3bits.SAMC1 = 1;  //(参考)0001: 1Tad    0010: 2Tad    0011: 3Tad  ・・・・
        AD1CON3bits.SAMC0 = 1;  //
        AD1CON3bits.ADCS7 = 0;  //AD変換時間の設定/AD1CON3bits.ADCS7 - AD1CON3bits.ADCS0(ADCS<7:0>)の8ビットでセット
                                                                //AD変換完了フラグAD1CON1bits.DONEにより、AD変換完了を検知する場合は設定不要
        AD1CON3bits.ADCS6 = 0;  //AD変換完了までののクロック数選択ビット
        AD1CON3bits.ADCS5 = 0;  //0000 0101: 1Tad = 6Tpb  (Tpb: PBCLKの周期)
        AD1CON3bits.ADCS4 = 0;  //(参考) 0000 0000: 1Tad = 2Tpb
        AD1CON3bits.ADCS3 = 0;  //      0000 0001: 1Tad = 3Tpb
        AD1CON3bits.ADCS2 = 1;  //      0000 0010: 1Tad = 4Tpb
        AD1CON3bits.ADCS1 = 0;  //                                ・・・・    
        AD1CON3bits.ADCS0 = 1;  //     1111 1111: 1Tad = 512Tpb

 //AD1CHSレジスタの設定 //SHAの+端子とー端子への接続(ポート)設定
        //マルチプレクサ:MUXB側
        AD1CHSbits.CH0NB = 0;   //負側入力選択ビット: 0:VR- 、1:AN1
        AD1CHSbits.CH0SB3 = 0;  //正側入力選択ビット//0000:AN0, 0001:AN1, 0011:AN2 ....  1111: AN15
        AD1CHSbits.CH0SB2 = 0;  //★MUXAだけを使うので、CH0SB0-CH0SB3は出力に無関係
        AD1CHSbits.CH0SB1 = 0;  //
        AD1CHSbits.CH0SB0 = 0;  //

        //マルチプレクサ:MUXA側
        AD1CHSbits.CH0NA = 0;   //負側入力選択ビット: 0:VR- 、1:AN1
     //   AD1CHSbits.CH0SA3 = 0;  //正側入力選択ビット//0000:AN0, 0001:AN1, 0010:AN2 ....  1111: AN15
     //   AD1CHSbits.CH0SA2 = 1;  //0100マルチプレクサMUXAの正側入力: AN4
     //   AD1CHSbits.CH0SA1 = 0;  //
     //   AD1CHSbits.CH0SA0 = 0;  //
        AD1CHSbits.CH0SA = 9;   //AN9

//AD1PCFGレジスタの設定 //アナログ入力orデジタル入力選択 //1:デジタル、 0:アナログ
        // ★デバイスリセットでは全ビット0となるためデフォルトではアナログ入力となるのでデジタルで使う多重ピンは、コンフィグレーションでデジタル設定が必要!! 
        AD1PCFGbits.PCFG15 = 1;//RB15/AN15
        AD1PCFGbits.PCFG14 = 1;//RB14/AN14
        AD1PCFGbits.PCFG13 = 1;//RB13/AN13
        AD1PCFGbits.PCFG12 = 1;//RB12/AN12
        AD1PCFGbits.PCFG11 = 1;//RB11/AN11
        AD1PCFGbits.PCFG10 = 1;//RB10/AN10
        AD1PCFGbits.PCFG9 = 0;//RB9/AN9 //アナログ
        AD1PCFGbits.PCFG8 = 1;//RB8/AN8
        AD1PCFGbits.PCFG7 = 1;//RB7/AN7
        AD1PCFGbits.PCFG6 = 1;//RB6/AN6
        AD1PCFGbits.PCFG5 = 1;//RB5/AN5
        AD1PCFGbits.PCFG4 = 1;//RB4/AN4
        AD1PCFGbits.PCFG3 = 1;//RB3/AN3
        AD1PCFGbits.PCFG2 = 1;//RB2/AN2
        AD1PCFGbits.PCFG1 = 1;//RB1/AN1
        AD1PCFGbits.PCFG0 = 1;//RB0/AN0


        //      AD1CSSLレジスタの設定
        //読み込むチャンネル(入力端子)をセットする//0:スキャンしない 1:スキャンする
        AD1CSSLbits.CSSL15 = 0; //AN15
        AD1CSSLbits.CSSL14 = 0; //AN14
        AD1CSSLbits.CSSL13 = 0; //AN13
        AD1CSSLbits.CSSL12 = 0; //AN12
        AD1CSSLbits.CSSL11 = 0; //AN11
        AD1CSSLbits.CSSL10 = 0; //AN10
        AD1CSSLbits.CSSL9 = 1;  //AN9   //スキャンする
        AD1CSSLbits.CSSL8 = 0;  //AN8
        AD1CSSLbits.CSSL7 = 0;  //AN7
        AD1CSSLbits.CSSL6 = 0;  //AN6
        AD1CSSLbits.CSSL5 = 0;  //AN5
        AD1CSSLbits.CSSL4 = 0;  //AN4
        AD1CSSLbits.CSSL3 = 0;  //AN3
        AD1CSSLbits.CSSL2 = 0;  //AN2
        AD1CSSLbits.CSSL0 = 0;  //AN0  



    //USB関係
    USBDeviceInit();
    USBOutHandle = 0;
    USBInHandle = 0;
    blinkStatusValid = TRUE; 
    USBDeviceAttach();


    while(1)
    {
        // USB接続中なら送受信実行
        if((USBDeviceState >= CONFIGURED_STATE)&&(USBSuspendControl!=1))ProcessIO();
    }
}



void ProcessIO(void)
{  
    if(!HIDRxHandleBusy(USBOutHandle))                          
    {  
        switch(ReceivedDataBuffer[0])   //コマンドの種類判定
        {
            //接続確認応答
            case 0x30: //
                SendBuf[2] = 'O';
                SendBuf[3] = 'K';
                if(!HIDTxHandleBusy(USBInHandle))
                USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&SendBuf[0],64);    //PC側に送信
                break;

            case 0x80:  //LED 点灯/消灯制御
                switch(ReceivedDataBuffer[1])
                {
                    case 0x30:  //RA2
                        if(ReceivedDataBuffer[2] == 0x30)
                        {
                            LATAbits.LATA2 = 0;    //消灯
                            SendBuf[2] = 0x30;
                        }
                        else
                        {
                            LATAbits.LATA2 = 1;    //点灯
                            SendBuf[2] = 0x31;
                        }
                        if(!HIDTxHandleBusy(USBInHandle))
                            USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&SendBuf[0],64);    //PC側に送信
                        break;
                    case 0x31:  //RA3
                        if(ReceivedDataBuffer[2] == 0x30)
                        {
                            LATAbits.LATA3 = 0;
                            SendBuf[3] = 0x30;
                        }
                        else
                        {
                            LATAbits.LATA3 = 1;
                            SendBuf[3] = 0x31;
                        }
                        if(!HIDTxHandleBusy(USBInHandle))
                            USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&SendBuf[0],64);    //PC側に送信
                        break;
                    case 0x32:  //RA4
                        if(ReceivedDataBuffer[2] == 0x30)
                        {
                            LATAbits.LATA4 = 0;
                            SendBuf[4] = 0x30;
                        }
                        else
                        {
                            LATAbits.LATA4 = 1;
                            SendBuf[4] = 0x31;
                        }
                        if(!HIDTxHandleBusy(USBInHandle))
                            USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&SendBuf[0],64);    //PC側に送信
                        break;
                    case 0x33:  //RA5
                        if(ReceivedDataBuffer[2] == 0x30)
                        {
                            LATAbits.LATA5 = 0;
                            SendBuf[5] = 0x30;
                        }
                        else
                        {
                          LATAbits.LATA5 = 1;
                          SendBuf[5] = 0x31;
                        }
                        if(!HIDTxHandleBusy(USBInHandle))
                            USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&SendBuf[0],64);    //PC側に送信
                         break;
                    default :
                        break;

                }

            case 0x81:  //スイッチの状態検出

                                if(ReceivedDataBuffer[1] == 0x31){
                                        if(PORTDbits.RD13 == 0)
                                                SendBuf[2] = 0x30;
                                        else
                                                SendBuf[2] = 0x31;
                                }
                                else if(ReceivedDataBuffer[1] == 0x32){
                                        if(PORTDbits.RD6 == 0)
                                                SendBuf[2] = 0x30;
                                        else
                                                SendBuf[2] = 0x31;
                                }
                                else if(ReceivedDataBuffer[1] == 0x33){
                                        if(PORTDbits.RD7 == 0)
                                                SendBuf[2] = 0x30;
                                        else
                                                SendBuf[2] = 0x31;
                                }
                                if(!HIDTxHandleBusy(USBInHandle))
                                        USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&SendBuf[0],64);    //PC側に送信
                                break;
             

            case 0x82: //VR電圧検出

                   AD1CON1bits.SAMP =1;            //サンプリング開始
                   while(!AD1CON1bits.DONE);       //AD変換終了フラグがたつ(1になるまで)待つ
                   AdcValue = ADC1BUF0;            //ADC1のバッファーからAD変換結果を読込む//★ADC1BUF1ではない
                 

                    ToSendDataBuffer[2] = AdcValue;     //下位8ビット at 10ビット
                    ToSendDataBuffer[3] = AdcValue >> 8;        //上位2ビット at 10ビット

                    USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&ToSendDataBuffer[0],64);   //PC側に送信
                
                break;
                
        }
    
        //次の受信実行
        USBOutHandle = HIDRxPacket(HID_EP, (BYTE*)&ReceivedDataBuffer, 64);
    }
}





// ******************************************************************************************************
// ************** USB Callback Functions ****************************************************************
// ******************************************************************************************************

void USBCBSuspend(void)
{
}

void USBCBWakeFromSuspend(void)
{
}

void USBCB_SOF_Handler(void)
{
}
void USBCBErrorHandler(void)
{
}
void USBCBCheckOtherReq(void)
{
    USBCheckHIDRequest();
}
void USBCBStdSetDscHandler(void)
{
}
void USBCBInitEP(void)
{
    //enable the HID endpoint
    USBEnableEndpoint(HID_EP,USB_IN_ENABLED|USB_OUT_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
    //Re-arm the OUT endpoint for the next packet
    USBOutHandle = HIDRxPacket(HID_EP,(BYTE*)&ReceivedDataBuffer,64);
}

void USBCBSendResume(void)
{
    static WORD delay_count;
    if(USBGetRemoteWakeupStatus() == TRUE) 
    {
        if(USBIsBusSuspended() == TRUE)
        {
            USBMaskInterrupts();
            
            //Clock switch to settings consistent with normal USB operation.
            USBCBWakeFromSuspend();
            USBSuspendControl = 0; 
            USBBusIsSuspended = FALSE;  //So we don't execute this code again, 
                                        //until a new suspend condition is detected.
            delay_count = 3600U;        
            do
            {
                delay_count--;
            }while(delay_count);
            
            //Now drive the resume K-state signalling onto the USB bus.
            USBResumeControl = 1;       // Start RESUME signaling
            delay_count = 1800U;        // Set RESUME line for 1-13 ms
            do
            {
                delay_count--;
            }while(delay_count);
            USBResumeControl = 0;       //Finished driving resume signalling

            USBUnmaskInterrupts();
        }
    }
}
BOOL USER_USB_CALLBACK_EVENT_HANDLER(int event, void *pdata, WORD size)
{
    switch(event)
    {
        case EVENT_TRANSFER:
            //Add application specific callback task or callback function here if desired.
            break;
        case EVENT_SOF:
            USBCB_SOF_Handler();
            break;
        case EVENT_SUSPEND:
            USBCBSuspend();
            break;
        case EVENT_RESUME:
            USBCBWakeFromSuspend();
            break;
        case EVENT_CONFIGURED: 
            USBCBInitEP();
            break;
        case EVENT_SET_DESCRIPTOR:
            USBCBStdSetDscHandler();
            break;
        case EVENT_EP0_REQUEST:
            USBCBCheckOtherReq();
            break;
        case EVENT_BUS_ERROR:
            USBCBErrorHandler();
            break;
        case EVENT_TRANSFER_TERMINATED:
            break;
        default:
            break;
    }      
    return TRUE; 
}


//--------------------------------------------------------------------
/********************************************************************
 FileName:      usb_descriptors.c
 Dependencies:  See INCLUDES section
 Processor:             PIC18 or PIC24 USB Microcontrollers
 Hardware:              The code is natively intended to be used on the following
                                hardware platforms: PICDEM?FS USB Demo Board, 
                                PIC18F87J50 FS USB Plug-In Module, or
                                Explorer 16 + PIC24 USB PIM.  The firmware may be
                                modified for use on other USB platforms by editing the
                                HardwareProfile.h file.
 Complier:      Microchip C18 (for PIC18) or C30 (for PIC24)
 Company:               Microchip Technology, Inc.

 Software License Agreement:

 The software supplied herewith by Microchip Technology Incorporated
 (the 鼎ompany? for its PICョ Microcontroller is intended and
 supplied to you, the Company痴 customer, for use solely and
 exclusively on Microchip PIC Microcontroller products. The
 software is owned by the Company and/or its supplier, and is
 protected under applicable copyright laws. All rights are reserved.
 Any use in violation of the foregoing restrictions may subject the
 user to criminal sanctions under applicable laws, as well as to
 civil liability for the breach of the terms and conditions of this
 license.

 THIS SOFTWARE IS PROVIDED IN AN 鄭S IS?CONDITION. NO WARRANTIES,
 WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
 TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
 IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
 CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.

*********************************************************************
-usb_descriptors.c-
-------------------------------------------------------------------
Filling in the descriptor values in the usb_descriptors.c file:
-------------------------------------------------------------------

[Device Descriptors]
The device descriptor is defined as a USB_DEVICE_DESCRIPTOR type.  
This type is defined in usb_ch9.h  Each entry into this structure
needs to be the correct length for the data type of the entry.

[Configuration Descriptors]
The configuration descriptor was changed in v2.x from a structure
to a BYTE array.  Given that the configuration is now a byte array
each byte of multi-byte fields must be listed individually.  This
means that for fields like the total size of the configuration where
the field is a 16-bit value "64,0," is the correct entry for a
configuration that is only 64 bytes long and not "64," which is one
too few bytes.

The configuration attribute must always have the _DEFAULT
definition at the minimum. Additional options can be ORed
to the _DEFAULT attribute. Available options are _SELF and _RWU.
These definitions are defined in the usb_device.h file. The
_SELF tells the USB host that this device is self-powered. The
_RWU tells the USB host that this device supports Remote Wakeup.

[Endpoint Descriptors]
Like the configuration descriptor, the endpoint descriptors were 
changed in v2.x of the stack from a structure to a BYTE array.  As
endpoint descriptors also has a field that are multi-byte entities,
please be sure to specify both bytes of the field.  For example, for
the endpoint size an endpoint that is 64 bytes needs to have the size
defined as "64,0," instead of "64,"

Take the following example:
    // Endpoint Descriptor //
    0x07,                       //the size of this descriptor //
    USB_DESCRIPTOR_ENDPOINT,    //Endpoint Descriptor
    _EP02_IN,                   //EndpointAddress
    _INT,                       //Attributes
    0x08,0x00,                  //size (note: 2 bytes)
    0x02,                       //Interval

The first two parameters are self-explanatory. They specify the
length of this endpoint descriptor (7) and the descriptor type.
The next parameter identifies the endpoint, the definitions are
defined in usb_device.h and has the following naming
convention:
_EP<##>_<dir>
where ## is the endpoint number and dir is the direction of
transfer. The dir has the value of either 'OUT' or 'IN'.
The next parameter identifies the type of the endpoint. Available
options are _BULK, _INT, _ISO, and _CTRL. The _CTRL is not
typically used because the default control transfer endpoint is
not defined in the USB descriptors. When _ISO option is used,
addition options can be ORed to _ISO. Example:
_ISO|_AD|_FE
This describes the endpoint as an isochronous pipe with adaptive
and feedback attributes. See usb_device.h and the USB
specification for details. The next parameter defines the size of
the endpoint. The last parameter in the polling interval.

-------------------------------------------------------------------
Adding a USB String
-------------------------------------------------------------------
A string descriptor array should have the following format:

rom struct{byte bLength;byte bDscType;word string[size];}sdxxx={
sizeof(sdxxx),DSC_STR,<text>};

The above structure provides a means for the C compiler to
calculate the length of string descriptor sdxxx, where xxx is the
index number. The first two bytes of the descriptor are descriptor
length and type. The rest <text> are string texts which must be
in the unicode format. The unicode format is achieved by declaring
each character as a word type. The whole text string is declared
as a word array with the number of characters equals to <size>.
<size> has to be manually counted and entered into the array
declaration. Let's study this through an example:
if the string is "USB" , then the string descriptor should be:
(Using index 02)
rom struct{byte bLength;byte bDscType;word string[3];}sd002={
sizeof(sd002),DSC_STR,'U','S','B'};

A USB project may have multiple strings and the firmware supports
the management of multiple strings through a look-up table.
The look-up table is defined as:
rom const unsigned char *rom USB_SD_Ptr[]={&sd000,&sd001,&sd002};

The above declaration has 3 strings, sd000, sd001, and sd002.
Strings can be removed or added. sd000 is a specialized string
descriptor. It defines the language code, usually this is
US English (0x0409). The index of the string must match the index
position of the USB_SD_Ptr array, &sd000 must be in position
USB_SD_Ptr[0], &sd001 must be in position USB_SD_Ptr[1] and so on.
The look-up table USB_SD_Ptr is used by the get string handler
function.

-------------------------------------------------------------------

The look-up table scheme also applies to the configuration
descriptor. A USB device may have multiple configuration
descriptors, i.e. CFG01, CFG02, etc. To add a configuration
descriptor, user must implement a structure similar to CFG01.
The next step is to add the configuration descriptor name, i.e.
cfg01, cfg02,.., to the look-up table USB_CD_Ptr. USB_CD_Ptr[0]
is a dummy place holder since configuration 0 is the un-configured
state according to the definition in the USB specification.

********************************************************************/
 
/*********************************************************************
 * Descriptor specific type definitions are defined in:
 * usb_device.h
 *
 * Configuration options are defined in:
 * usb_config.h
 ********************************************************************/
#ifndef __USB_DESCRIPTORS_C
#define __USB_DESCRIPTORS_C

/** INCLUDES *******************************************************/
#include "./USB/usb.h"
#include "./USB/usb_function_hid.h"

/** CONSTANTS ******************************************************/
#if defined(__18CXX)
#pragma romdata
#endif

/* Device Descriptor */
ROM USB_DEVICE_DESCRIPTOR device_dsc=
{
    0x12,    // Size of this descriptor in bytes
    USB_DESCRIPTOR_DEVICE,                // DEVICE descriptor type
    0x0200,                 // USB Spec Release Number in BCD format
    0x00,                   // Class Code
    0x00,                   // Subclass code
    0x00,                   // Protocol code
    USB_EP0_BUFF_SIZE,          // Max packet size for EP0, see usb_config.h
    0x04D8,                 // Vendor ID
    0x003F,                 // Product ID: Custom HID device demo
    0x0002,                 // Device release number in BCD format
    0x01,                   // Manufacturer string index
    0x02,                   // Product string index
    0x00,                   // Device serial number string index
    0x01                    // Number of possible configurations
};

/* Configuration 1 Descriptor */
ROM BYTE configDescriptor1[]={
    /* Configuration Descriptor */
    0x09,//sizeof(USB_CFG_DSC),    // Size of this descriptor in bytes
    USB_DESCRIPTOR_CONFIGURATION,                // CONFIGURATION descriptor type
    0x29,0x00,            // Total length of data for this cfg
    1,                      // Number of interfaces in this cfg
    1,                      // Index value of this configuration
    0,                      // Configuration string index
    _DEFAULT | _SELF,               // Attributes, see usb_device.h
    50,                     // Max power consumption (2X mA)
                                                        
    /* Interface Descriptor */
    0x09,//sizeof(USB_INTF_DSC),   // Size of this descriptor in bytes
    USB_DESCRIPTOR_INTERFACE,               // INTERFACE descriptor type
    0,                      // Interface Number
    0,                      // Alternate Setting Number
    2,                      // Number of endpoints in this intf
    HID_INTF,               // Class code
    0,     // Subclass code
    0,     // Protocol code
    0,                      // Interface string index

    /* HID Class-Specific Descriptor */
    0x09,//sizeof(USB_HID_DSC)+3,    // Size of this descriptor in bytes
    DSC_HID,                // HID descriptor type
    0x11,0x01,                 // HID Spec Release Number in BCD format (1.11)
    0x00,                   // Country Code (0x00 for Not supported)
    HID_NUM_OF_DSC,         // Number of class descriptors, see usbcfg.h
    DSC_RPT,                // Report descriptor type
    HID_RPT01_SIZE,0x00,//sizeof(hid_rpt01),      // Size of the report descriptor
    
    /* Endpoint Descriptor */
    0x07,/*sizeof(USB_EP_DSC)*/
    USB_DESCRIPTOR_ENDPOINT,    //Endpoint Descriptor
    HID_EP | _EP_IN,                   //EndpointAddress
    _INTERRUPT,                       //Attributes
    0x40,0x00,                  //size
    0x01,                        //Interval

    /* Endpoint Descriptor */
    0x07,/*sizeof(USB_EP_DSC)*/
    USB_DESCRIPTOR_ENDPOINT,    //Endpoint Descriptor
    HID_EP | _EP_OUT,                   //EndpointAddress
    _INTERRUPT,                       //Attributes
    0x40,0x00,                  //size
    0x01                        //Interval
};

//Language code string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[1];}sd000={
sizeof(sd000),USB_DESCRIPTOR_STRING,{0x0409
}};

//Manufacturer string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[25];}sd001={
sizeof(sd001),USB_DESCRIPTOR_STRING,
{'M','i','c','r','o','c','h','i','p',' ',
'T','e','c','h','n','o','l','o','g','y',' ','I','n','c','.'
}};

//Product string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[22];}sd002={
sizeof(sd002),USB_DESCRIPTOR_STRING,
{'S','i','m','p','l','e',' ','H','I','D',' ',
'D','e','v','i','c','e',' ','D','e','m','o'
}};

//Class specific descriptor - HID 
ROM struct{BYTE report[HID_RPT01_SIZE];}hid_rpt01={
{
    0x06, 0x00, 0xFF,       // Usage Page = 0xFF00 (Vendor Defined Page 1)
    0x09, 0x01,             // Usage (Vendor Usage 1)
    0xA1, 0x01,             // Collection (Application)
    0x19, 0x01,             //      Usage Minimum 
    0x29, 0x40,             //      Usage Maximum       //64 input usages total (0x01 to 0x40)
    0x15, 0x01,             //      Logical Minimum (data bytes in the report may have minimum value = 0x00)
    0x25, 0x40,                 //      Logical Maximum (data bytes in the report may have maximum value = 0x00FF = unsigned 255)
    0x75, 0x08,             //      Report Size: 8-bit field size
    0x95, 0x40,             //      Report Count: Make sixty-four 8-bit fields (the next time the parser hits an "Input", "Output", or "Feature" item)
    0x81, 0x00,             //      Input (Data, Array, Abs): Instantiates input packet fields based on the above report size, count, logical min/max, and usage.
    0x19, 0x01,             //      Usage Minimum 
    0x29, 0x40,             //      Usage Maximum       //64 output usages total (0x01 to 0x40)
    0x91, 0x00,             //      Output (Data, Array, Abs): Instantiates output packet fields.  Uses same report size and count as "Input" fields, since nothing new/different was specified to the parser since the "Input" item.
    0xC0}                   // End Collection
};                  


//Array of configuration descriptors
ROM BYTE *ROM USB_CD_Ptr[]=
{
    (ROM BYTE *ROM)&configDescriptor1
};

//Array of string descriptors
ROM BYTE *ROM USB_SD_Ptr[]=
{
    (ROM BYTE *ROM)&sd000,
    (ROM BYTE *ROM)&sd001,
    (ROM BYTE *ROM)&sd002
};

/** EOF usb_descriptors.c ***************************************************/

#endif

 

<実行結果>
 PC画面のLED0,LED2、LED3ボタンをクリックして キバン上のLEDを点灯させたあと、キバン上のSW1とSW3をおした時のPCのスクリーンショット画像とキバンの写真です。
ADコンバータで検出された電圧が ダイアログのテキストボックスに小数点以下2桁で3.53[V}と表示されています。

パソコン画面の
  ダイアログ
PIC32MX795F512L キバン上で
  SW1 とSW3を押したところ

■ PIC32MX795F512L  HIDクラス 漢字を含む文字列の送受信(キャラクタ液晶)

PIC32MX795F512Lにキャラクタ液晶を接続した USB通信 送受信の例を紹介します。   → PC側 VC++ ソフト

<試作品仕様>
 ・PC側からデータをPIC側にUSB HIDクラス通信で送信する。
 ・送信文字コードはシフトJISを使用する
 ・PIC側では受信した文字列を液晶上段に、受信データに基づき返信したデータを液晶下段に表示する。
 ・PC側でも受信したデータをリストボックスに表示する。
 ・PC側からの送信データ 及びPIC側からの返信データは以下とする。
     @ U.K.       →  London
     A America    →  Washington
     B Japan      →  0x938c(東)0x8b9e(京)
     C 中(0x9286)国 (0x8D91)   → 北(0x966B)京(0x8B9E)
     D I am a boy.   →  Pardon ?

<試作品回路図>(→回路図のPDFファイル







<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています





   <プログラム例>

//main.c        //32MX795

#include "./USB/usb.h"
#include "HardwareProfile.h"
#include "./USB/usb_function_hid.h"

#include "1lcd_lib_C32.h"

//システムクロック80MHz  ペリフェラルクロック60MHz
        #pragma config UPLLEN   = ON        // USB PLL Enabled
        #pragma config FPLLMUL  = MUL_15        // PLL Multiplier
        #pragma config UPLLIDIV = DIV_2         // USB PLL Input Divider
        #pragma config FPLLIDIV = DIV_2         // PLL Input Divider
        #pragma config FPLLODIV = DIV_1         // PLL Output Divider
        #pragma config FPBDIV   = DIV_1         // Peripheral Clock divisor
        #pragma config FWDTEN   = OFF           // Watchdog Timer
        #pragma config WDTPS    = PS1           // Watchdog Timer Postscale
        #pragma config FCKSM    = CSDCMD        // Clock Switching & Fail Safe Clock Monitor
        #pragma config OSCIOFNC = OFF           // CLKO Enable
        #pragma config POSCMOD  = HS            // Primary Oscillator
        #pragma config IESO     = OFF           // Internal/External Switch-over
        #pragma config FSOSCEN  = OFF           // Secondary Oscillator Enable (KLO was off)
        #pragma config FNOSC    = PRIPLL        // Oscillator Selection
        #pragma config CP       = OFF           // Code Protect
        #pragma config BWP      = OFF           // Boot Flash Write Protect
        #pragma config PWP      = OFF           // Program Flash Write Protect
        #pragma config ICESEL   = ICS_PGx2      // ICE/ICD Comm Channel Select


#define RX_DATA_BUFFER_ADDRESS
#define TX_DATA_BUFFER_ADDRESS

unsigned char ReceivedDataBuffer[64] RX_DATA_BUFFER_ADDRESS;
unsigned char ToSendDataBuffer[64] TX_DATA_BUFFER_ADDRESS;
unsigned char SendBuf[64];

unsigned char myChr[17];    //文字列部分


char Buf[64];   //文字列のバッファー用レジスタ

unsigned char* str1;
char* str2;
unsigned char Japan[]   = "Japan           ";
unsigned char UK[]      = "U.K.            ";
unsigned char America[] = "America         ";
                                //unsigned char Chuugoku[] = "Chuugoku        ";
unsigned char Chuugoku[] = {0x92,0x86,0x8D,0x91,' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
                        //中[0x9286]  国[0x8D91]

//char Tokyo[]      = "Tokyo           \r";
char Tokyo[]            = {0x93,0x8C,0x8B,0x9E,' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','\r'};
                                        //シフトJIS 東[938C]、京[8B9E]
char Pekin[]            = {0x96,0x6B,0x8B,0x9E,' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','\r'};
                            //シフトJIS  北[966B]、京[8B9E]

char London[]           = "London          \r";
char Washington[]       = "Washington      \r";
char Pardon[]           = "Pardon ?        \r";



BOOL blinkStatusValid;
USB_HANDLE USBGenericOutHandle; //送信ハンドル
USB_HANDLE USBGenericInHandle;  //受信ハンドル



USB_HANDLE USBOutHandle = 0;    //USB handle.  Must be initialized to 0 at startup.
USB_HANDLE USBInHandle = 0;     //USB handle.  Must be initialized to 0 at startup.


void BlinkUSBStatus(void);
void ProcessIO(void);
void YourHighPriorityISRCode();
void YourLowPriorityISRCode();
void USBCBSendResume(void);





void delay_us(unsigned int usec)        //1μsec遅延関数
{
        int count;

        count = (int)(Clock/20000000)*usec;

        do      //実測: at Clock=80000000
        {       //delay_us(1000)→1003μsec、 delay_us(100)→102μsec、delay_us(10)→11μsec、delay_us(1)→1.6μsec

                asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");
                asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");

                count--;
        }while(count != 0);
}

void delay_ms(unsigned int msec)        //1msec遅延関数
{
        unsigned int i;

        for(i=0; i<msec; i++)
        delay_us(1000);
}



int main(void)
{
    int i ;


    for(i = 0; i < 65; i++)Buf[i] = ' ';

    SYSTEMConfigPerformance(60000000);  //システム最適化
    DDPCONbits.JTAGEN = 0;  //JTAG無効化

    AD1PCFG = 0xFFFF;   //全RBポートデジタルピンとして使用
 

    TRISDbits.TRISD6=1;
    TRISDbits.TRISD7=1;


    TRISBbits.TRISB15 = 0;       //キャラクタ液晶ポート設定
    TRISBbits.TRISB14 = 0;       //キャラクタ液晶ポート設定
    TRISBbits.TRISB13 = 0;       //キャラクタ液晶ポート設定
    TRISBbits.TRISB12 = 0;       //キャラクタ液晶ポート設定
    TRISAbits.TRISA9 = 0;       //キャラクタ液晶ポート設定
    TRISAbits.TRISA10 = 0;       //キャラクタ液晶ポート設定



        //USB関係
        USBDeviceInit();
        USBOutHandle = 0;
        USBInHandle = 0;
        blinkStatusValid = TRUE;
        USBDeviceAttach();

        lcd_init();        // LCD初期化
        lcd_clear();        //クリア

        lcd_cmd(0b00001100);    // カーソル:OFF  ブリンク:OFF

        lcd_cmd(0x80);          //1目の先頭へ


                str1 = &myChr[0];

        sprintf(Buf,"Iruma ");//
      lcd_str(str1);   
        lcd_str(Buf);                   //液晶表示

        lcd_cmd(0xC0);          //2行目の先頭へ
        sprintf(Buf,"   World !!");     //
        lcd_str(Buf);           // 開始メッセージ1行目表示

        delay_ms(3000);


    while(1)
    {
        // USB接続中なら送受信実行
        if((USBDeviceState >= CONFIGURED_STATE)&&(USBSuspendControl!=1))ProcessIO();
    }
}



void ProcessIO(void)
{
    int i;
    if(!HIDRxHandleBusy(USBOutHandle))                          
    {  
        switch(ReceivedDataBuffer[0])   //コマンドの種類判定
        {
            //接続確認応答
            case 0x30: //
                SendBuf[2] = 'O';
                SendBuf[3] = 'K';
                if(!HIDTxHandleBusy(USBInHandle))
                USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&SendBuf[0],64);    //PC側に送信

                break;

            case 0x80:  //受信文字列判定   & 対応文字列返信

                for(i = 1; i < 17; i++)myChr[i-1] = ReceivedDataBuffer[i];
              
                str1 = &myChr[0];
            //    str1 = &ReceivedDataBuffer[0];

                if(strcmp(str1,Japan) == 0)
                {

                        lcd_cmd(0x80);  //1行目へ
                        sprintf(Buf,"%s",str1);
                        lcd_str(Buf);       //受信データを液晶に表示
                        lcd_cmd(0xC0);  //2行目
                        sprintf(Buf,"%x%x%x%x",Tokyo[0],Tokyo[1],Tokyo[2],Tokyo[3]);
                                                        //sprintf()のバグのため(?)か C18では制御文字の前にffをつける仕様になっているためか
                                                        //液晶には ”ff93ff8Cff8Bff9E” と表示される
                                                        //シフトJIS 東[938C]、京[8B9E]
                        lcd_str(Buf);       //送信データを液晶に表示

                        sprintf(Buf,"%c%c%c%c",Tokyo[0],Tokyo[1],Tokyo[2],Tokyo[3]);    //送信するときは%cにして送信
                }
                else if((myChr[0] == Chuugoku[0]) && (myChr[1] == Chuugoku[1]) && (myChr[2] == Chuugoku[2]) && (myChr[3] == Chuugoku[3]) &&
                        (myChr[4] == Chuugoku[4]) && (myChr[5] == Chuugoku[5]) && (myChr[6] == Chuugoku[6]) && (myChr[7] == Chuugoku[7]) &&
                        (myChr[8] == Chuugoku[8]) && (myChr[9] == Chuugoku[9]) && (myChr[10] == Chuugoku[10]) && (myChr[11] == Chuugoku[11]) &&
                        (myChr[12] == Chuugoku[12]) && (myChr[13] == Chuugoku[13]) && (myChr[14] == Chuugoku[14]) && (myChr[15] == Chuugoku[15]))
         //       else if(strcmp(str1,Chuugoku) == 0)   //NG: strcmp( )はASCII文字のみに対応 制御文字には対応していない
                {
                      lcd_cmd(0x80);  //1行目へ
                        sprintf(Buf,"%s",str1);
                        lcd_str(Buf);       //受信データを液晶に表示
                        lcd_cmd(0xC0);  //2行目
                        sprintf(Buf,"%x%x%x%x",Pekin[0],Pekin[1],Pekin[2],Pekin[3]);
                                                        //sprintf()のバグのため(?)か C18では制御文字の前にffをつける仕様になっているためか
                                                        //液晶には ”ff93ff8Cff8Bff9E” と表示される
                                                        //シフトJIS 東[938C]、京[8B9E]
                        lcd_str(Buf);       //送信データを液晶に表示

                        sprintf(Buf,"%c%c%c%c",Pekin[0],Pekin[1],Pekin[2],Pekin[3]);    //送信するときは%cにして送信

                }
                else if(strcmp(str1,UK) == 0)
                {
                        str2 = London;
                        lcd_cmd(0x80);  //1行目へ
                        sprintf(Buf,"%s",str1);
                        lcd_str(Buf);       //受信データを液晶に表示
                        lcd_cmd(0xC0);  //2行目
                        sprintf(Buf,"%s",str2);
                        lcd_str(Buf);       //送信データを液晶に表示
                }
                else if(strcmp(str1,America) == 0)
                {
                        str2 = Washington;
                        lcd_cmd(0x80);  //1行目へ
                        sprintf(Buf,"%s",str1);
                        lcd_str(Buf);       //受信データを液晶に表示
                        lcd_cmd(0xC0);  //2行目
                        sprintf(Buf,"%s",str2);
                        lcd_str(Buf);       //送信データを液晶に表示
                }
                else
                {
                        str2 = Pardon;
                        lcd_cmd(0x80);  //1行目へ
                        sprintf(Buf,"%s",str1);
                        lcd_str(Buf);       //受信データを液晶に表示
                        lcd_cmd(0xC0);  //2行目
                        sprintf(Buf,"%s",str2);
                        lcd_str(Buf);       //送信データを液晶に表示
                }
                
                for(i = 0; i < 18; i++)SendBuf[i] = Buf[i]; //送信データセット




                if(!HIDTxHandleBusy(USBInHandle))
                USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&SendBuf[0],64);    //PC側に送信
                break;
                
        }
    
        //次の受信実行
        USBOutHandle = HIDRxPacket(HID_EP, (BYTE*)&ReceivedDataBuffer, 64);
    }
}





// ******************************************************************************************************
// ************** USB Callback Functions ****************************************************************
// ******************************************************************************************************

void USBCBSuspend(void)
{
}

void USBCBWakeFromSuspend(void)
{
}

void USBCB_SOF_Handler(void)
{
}
void USBCBErrorHandler(void)
{
}
void USBCBCheckOtherReq(void)
{
    USBCheckHIDRequest();
}
void USBCBStdSetDscHandler(void)
{
}
void USBCBInitEP(void)
{
    //enable the HID endpoint
    USBEnableEndpoint(HID_EP,USB_IN_ENABLED|USB_OUT_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
    //Re-arm the OUT endpoint for the next packet
    USBOutHandle = HIDRxPacket(HID_EP,(BYTE*)&ReceivedDataBuffer,64);
}

void USBCBSendResume(void)
{
    static WORD delay_count;
    if(USBGetRemoteWakeupStatus() == TRUE) 
    {
        if(USBIsBusSuspended() == TRUE)
        {
            USBMaskInterrupts();
            
            //Clock switch to settings consistent with normal USB operation.
            USBCBWakeFromSuspend();
            USBSuspendControl = 0; 
            USBBusIsSuspended = FALSE;  //So we don't execute this code again, 
                                        //until a new suspend condition is detected.
            delay_count = 3600U;        
            do
            {
                delay_count--;
            }while(delay_count);
            
            //Now drive the resume K-state signalling onto the USB bus.
            USBResumeControl = 1;       // Start RESUME signaling
            delay_count = 1800U;        // Set RESUME line for 1-13 ms
            do
            {
                delay_count--;
            }while(delay_count);
            USBResumeControl = 0;       //Finished driving resume signalling

            USBUnmaskInterrupts();
        }
    }
}
BOOL USER_USB_CALLBACK_EVENT_HANDLER(int event, void *pdata, WORD size)
{
    switch(event)
    {
        case EVENT_TRANSFER:
            //Add application specific callback task or callback function here if desired.
            break;
        case EVENT_SOF:
            USBCB_SOF_Handler();
            break;
        case EVENT_SUSPEND:
            USBCBSuspend();
            break;
        case EVENT_RESUME:
            USBCBWakeFromSuspend();
            break;
        case EVENT_CONFIGURED: 
            USBCBInitEP();
            break;
        case EVENT_SET_DESCRIPTOR:
            USBCBStdSetDscHandler();
            break;
        case EVENT_EP0_REQUEST:
            USBCBCheckOtherReq();
            break;
        case EVENT_BUS_ERROR:
            USBCBErrorHandler();
            break;
        case EVENT_TRANSFER_TERMINATED:
            break;
        default:
            break;
    }      
    return TRUE; 
}





/********************************************************************
 FileName:      usb_descriptors.c
 Dependencies:  See INCLUDES section
 Processor:             PIC18 or PIC24 USB Microcontrollers
 Hardware:              The code is natively intended to be used on the following
                                hardware platforms: PICDEM?FS USB Demo Board, 
                                PIC18F87J50 FS USB Plug-In Module, or
                                Explorer 16 + PIC24 USB PIM.  The firmware may be
                                modified for use on other USB platforms by editing the
                                HardwareProfile.h file.
 Complier:      Microchip C18 (for PIC18) or C30 (for PIC24)
 Company:               Microchip Technology, Inc.

 Software License Agreement:

 The software supplied herewith by Microchip Technology Incorporated
 (the 鼎ompany? for its PICョ Microcontroller is intended and
 supplied to you, the Company痴 customer, for use solely and
 exclusively on Microchip PIC Microcontroller products. The
 software is owned by the Company and/or its supplier, and is
 protected under applicable copyright laws. All rights are reserved.
 Any use in violation of the foregoing restrictions may subject the
 user to criminal sanctions under applicable laws, as well as to
 civil liability for the breach of the terms and conditions of this
 license.

 THIS SOFTWARE IS PROVIDED IN AN 鄭S IS?CONDITION. NO WARRANTIES,
 WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
 TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
 IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
 CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.

*********************************************************************
-usb_descriptors.c-
-------------------------------------------------------------------
Filling in the descriptor values in the usb_descriptors.c file:
-------------------------------------------------------------------

[Device Descriptors]
The device descriptor is defined as a USB_DEVICE_DESCRIPTOR type.  
This type is defined in usb_ch9.h  Each entry into this structure
needs to be the correct length for the data type of the entry.

[Configuration Descriptors]
The configuration descriptor was changed in v2.x from a structure
to a BYTE array.  Given that the configuration is now a byte array
each byte of multi-byte fields must be listed individually.  This
means that for fields like the total size of the configuration where
the field is a 16-bit value "64,0," is the correct entry for a
configuration that is only 64 bytes long and not "64," which is one
too few bytes.

The configuration attribute must always have the _DEFAULT
definition at the minimum. Additional options can be ORed
to the _DEFAULT attribute. Available options are _SELF and _RWU.
These definitions are defined in the usb_device.h file. The
_SELF tells the USB host that this device is self-powered. The
_RWU tells the USB host that this device supports Remote Wakeup.

[Endpoint Descriptors]
Like the configuration descriptor, the endpoint descriptors were 
changed in v2.x of the stack from a structure to a BYTE array.  As
endpoint descriptors also has a field that are multi-byte entities,
please be sure to specify both bytes of the field.  For example, for
the endpoint size an endpoint that is 64 bytes needs to have the size
defined as "64,0," instead of "64,"

Take the following example:
    // Endpoint Descriptor //
    0x07,                       //the size of this descriptor //
    USB_DESCRIPTOR_ENDPOINT,    //Endpoint Descriptor
    _EP02_IN,                   //EndpointAddress
    _INT,                       //Attributes
    0x08,0x00,                  //size (note: 2 bytes)
    0x02,                       //Interval

The first two parameters are self-explanatory. They specify the
length of this endpoint descriptor (7) and the descriptor type.
The next parameter identifies the endpoint, the definitions are
defined in usb_device.h and has the following naming
convention:
_EP<##>_<dir>
where ## is the endpoint number and dir is the direction of
transfer. The dir has the value of either 'OUT' or 'IN'.
The next parameter identifies the type of the endpoint. Available
options are _BULK, _INT, _ISO, and _CTRL. The _CTRL is not
typically used because the default control transfer endpoint is
not defined in the USB descriptors. When _ISO option is used,
addition options can be ORed to _ISO. Example:
_ISO|_AD|_FE
This describes the endpoint as an isochronous pipe with adaptive
and feedback attributes. See usb_device.h and the USB
specification for details. The next parameter defines the size of
the endpoint. The last parameter in the polling interval.

-------------------------------------------------------------------
Adding a USB String
-------------------------------------------------------------------
A string descriptor array should have the following format:

rom struct{byte bLength;byte bDscType;word string[size];}sdxxx={
sizeof(sdxxx),DSC_STR,<text>};

The above structure provides a means for the C compiler to
calculate the length of string descriptor sdxxx, where xxx is the
index number. The first two bytes of the descriptor are descriptor
length and type. The rest <text> are string texts which must be
in the unicode format. The unicode format is achieved by declaring
each character as a word type. The whole text string is declared
as a word array with the number of characters equals to <size>.
<size> has to be manually counted and entered into the array
declaration. Let's study this through an example:
if the string is "USB" , then the string descriptor should be:
(Using index 02)
rom struct{byte bLength;byte bDscType;word string[3];}sd002={
sizeof(sd002),DSC_STR,'U','S','B'};

A USB project may have multiple strings and the firmware supports
the management of multiple strings through a look-up table.
The look-up table is defined as:
rom const unsigned char *rom USB_SD_Ptr[]={&sd000,&sd001,&sd002};

The above declaration has 3 strings, sd000, sd001, and sd002.
Strings can be removed or added. sd000 is a specialized string
descriptor. It defines the language code, usually this is
US English (0x0409). The index of the string must match the index
position of the USB_SD_Ptr array, &sd000 must be in position
USB_SD_Ptr[0], &sd001 must be in position USB_SD_Ptr[1] and so on.
The look-up table USB_SD_Ptr is used by the get string handler
function.

-------------------------------------------------------------------

The look-up table scheme also applies to the configuration
descriptor. A USB device may have multiple configuration
descriptors, i.e. CFG01, CFG02, etc. To add a configuration
descriptor, user must implement a structure similar to CFG01.
The next step is to add the configuration descriptor name, i.e.
cfg01, cfg02,.., to the look-up table USB_CD_Ptr. USB_CD_Ptr[0]
is a dummy place holder since configuration 0 is the un-configured
state according to the definition in the USB specification.

********************************************************************/
 
/*********************************************************************
 * Descriptor specific type definitions are defined in:
 * usb_device.h
 *
 * Configuration options are defined in:
 * usb_config.h
 ********************************************************************/
#ifndef __USB_DESCRIPTORS_C
#define __USB_DESCRIPTORS_C

/** INCLUDES *******************************************************/
#include "./USB/usb.h"
#include "./USB/usb_function_hid.h"

/** CONSTANTS ******************************************************/
#if defined(__18CXX)
#pragma romdata
#endif

/* Device Descriptor */
ROM USB_DEVICE_DESCRIPTOR device_dsc=
{
    0x12,    // Size of this descriptor in bytes
    USB_DESCRIPTOR_DEVICE,                // DEVICE descriptor type
    0x0200,                 // USB Spec Release Number in BCD format
    0x00,                   // Class Code
    0x00,                   // Subclass code
    0x00,                   // Protocol code
    USB_EP0_BUFF_SIZE,          // Max packet size for EP0, see usb_config.h
    0x04D8,                 // Vendor ID
    0x003F,                 // Product ID: Custom HID device demo
    0x0002,                 // Device release number in BCD format
    0x01,                   // Manufacturer string index
    0x02,                   // Product string index
    0x00,                   // Device serial number string index
    0x01                    // Number of possible configurations
};

/* Configuration 1 Descriptor */
ROM BYTE configDescriptor1[]={
    /* Configuration Descriptor */
    0x09,//sizeof(USB_CFG_DSC),    // Size of this descriptor in bytes
    USB_DESCRIPTOR_CONFIGURATION,                // CONFIGURATION descriptor type
    0x29,0x00,            // Total length of data for this cfg
    1,                      // Number of interfaces in this cfg
    1,                      // Index value of this configuration
    0,                      // Configuration string index
    _DEFAULT | _SELF,               // Attributes, see usb_device.h
    50,                     // Max power consumption (2X mA)
                                                        
    /* Interface Descriptor */
    0x09,//sizeof(USB_INTF_DSC),   // Size of this descriptor in bytes
    USB_DESCRIPTOR_INTERFACE,               // INTERFACE descriptor type
    0,                      // Interface Number
    0,                      // Alternate Setting Number
    2,                      // Number of endpoints in this intf
    HID_INTF,               // Class code
    0,     // Subclass code
    0,     // Protocol code
    0,                      // Interface string index

    /* HID Class-Specific Descriptor */
    0x09,//sizeof(USB_HID_DSC)+3,    // Size of this descriptor in bytes
    DSC_HID,                // HID descriptor type
    0x11,0x01,                 // HID Spec Release Number in BCD format (1.11)
    0x00,                   // Country Code (0x00 for Not supported)
    HID_NUM_OF_DSC,         // Number of class descriptors, see usbcfg.h
    DSC_RPT,                // Report descriptor type
    HID_RPT01_SIZE,0x00,//sizeof(hid_rpt01),      // Size of the report descriptor
    
    /* Endpoint Descriptor */
    0x07,/*sizeof(USB_EP_DSC)*/
    USB_DESCRIPTOR_ENDPOINT,    //Endpoint Descriptor
    HID_EP | _EP_IN,                   //EndpointAddress
    _INTERRUPT,                       //Attributes
    0x40,0x00,                  //size
    0x01,                        //Interval

    /* Endpoint Descriptor */
    0x07,/*sizeof(USB_EP_DSC)*/
    USB_DESCRIPTOR_ENDPOINT,    //Endpoint Descriptor
    HID_EP | _EP_OUT,                   //EndpointAddress
    _INTERRUPT,                       //Attributes
    0x40,0x00,                  //size
    0x01                        //Interval
};

//Language code string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[1];}sd000={
sizeof(sd000),USB_DESCRIPTOR_STRING,{0x0409
}};

//Manufacturer string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[25];}sd001={
sizeof(sd001),USB_DESCRIPTOR_STRING,
{'M','i','c','r','o','c','h','i','p',' ',
'T','e','c','h','n','o','l','o','g','y',' ','I','n','c','.'
}};

//Product string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[22];}sd002={
sizeof(sd002),USB_DESCRIPTOR_STRING,
{'S','i','m','p','l','e',' ','H','I','D',' ',
'D','e','v','i','c','e',' ','D','e','m','o'
}};

//Class specific descriptor - HID 
ROM struct{BYTE report[HID_RPT01_SIZE];}hid_rpt01={
{
    0x06, 0x00, 0xFF,       // Usage Page = 0xFF00 (Vendor Defined Page 1)
    0x09, 0x01,             // Usage (Vendor Usage 1)
    0xA1, 0x01,             // Collection (Application)
    0x19, 0x01,             //      Usage Minimum 
    0x29, 0x40,             //      Usage Maximum       //64 input usages total (0x01 to 0x40)
    0x15, 0x01,             //      Logical Minimum (data bytes in the report may have minimum value = 0x00)
    0x25, 0x40,                 //      Logical Maximum (data bytes in the report may have maximum value = 0x00FF = unsigned 255)
    0x75, 0x08,             //      Report Size: 8-bit field size
    0x95, 0x40,             //      Report Count: Make sixty-four 8-bit fields (the next time the parser hits an "Input", "Output", or "Feature" item)
    0x81, 0x00,             //      Input (Data, Array, Abs): Instantiates input packet fields based on the above report size, count, logical min/max, and usage.
    0x19, 0x01,             //      Usage Minimum 
    0x29, 0x40,             //      Usage Maximum       //64 output usages total (0x01 to 0x40)
    0x91, 0x00,             //      Output (Data, Array, Abs): Instantiates output packet fields.  Uses same report size and count as "Input" fields, since nothing new/different was specified to the parser since the "Input" item.
    0xC0}                   // End Collection
};                  


//Array of configuration descriptors
ROM BYTE *ROM USB_CD_Ptr[]=
{
    (ROM BYTE *ROM)&configDescriptor1
};

//Array of string descriptors
ROM BYTE *ROM USB_SD_Ptr[]=
{
    (ROM BYTE *ROM)&sd000,
    (ROM BYTE *ROM)&sd001,
    (ROM BYTE *ROM)&sd002
};

/** EOF usb_descriptors.c ***************************************************/

#endif




//*************************************************************************
//インクルードファイル    1lcd_lib_C32.h
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C32コンパイラ対応等で変更したものです。
//*************************************************************************

#include <proc/p32mx795f512l.h>         //PIC32MX460F512L

#define Clock   80000000        // 単位はHzで指定


// LCDポート設定
#define lcd_port_DB7    LATBbits.LATB15 //LCDのDB7(14番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB6    LATBbits.LATB14 //LCDのDB6(13番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB5    LATBbits.LATB13 //のDB5(12番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB4    LATBbits.LATB12 //LCDのDB4(11番ピン)に接続されつPIC側ポート番号設定
#define lcd_rs                  LATAbits.LATA9  //LCDのrs(4番ピン)に接続されるPIC側ポート番号設定
#define lcd_stb                 LATAbits.LATA10 //LCDのstb(6番ピン)に接続されるPIC側ポート番号設定



void lcd_out(char code, char flag);
void lcd_data(char asci);
void lcd_cmd(char cmd);
void lcd_clear(void);
void lcd_init(void);
void lcd_str(char *str);



//**************************************************************************
//インクルードファイル    1lcd_lib_C32.c
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C32コンパイラ対応等で変更したものです。
//**************************************************************************

///////////////////////////////////////////////
//  液晶表示器制御ライブラリ for C32コンパイラー
//  内蔵関数は以下
//    lcd_init()    ----- 初期化
//    lcd_cmd(cmd)  ----- コマンド出力
//    lcd_data(chr) ----- 1文字表示出力
//    lcd_clear()   ----- 全消去
//    lcd_str(str*) ----- 文字列表示 
//////////////////////////////////////////////

#include        "1lcd_lib_C32.h"

void lcd_delay_us(unsigned int usec)    //1μsec遅延関数
{
        int count;

        count = (int)(Clock/20000000)*usec;
        do
        {
                asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");
                asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");
                count--;        
        }while(count != 0);
}

void lcd_delay_ms(unsigned int msec)    //1msec遅延関数
{
        unsigned int i;
        
        for(i=0; i<msec; i++)
        lcd_delay_us(1000);
}


//////// データ出力サブ関数
void lcd_out(char code, char flag)
{
        if(code & 0b10000000)lcd_port_DB7 = 1;  //LCDのDB7への出力セット
        else lcd_port_DB7 = 0;
        if(code & 0b01000000)lcd_port_DB6 = 1;  //LCDのDB6への出力セット
        else lcd_port_DB6 = 0;
        if(code & 0b00100000)lcd_port_DB5 = 1;  //LCDのDB5への出力セット
        else lcd_port_DB5 = 0;
        if(code & 0b00010000)lcd_port_DB4 = 1;  //LCDのDB4への出力セット
        else lcd_port_DB4 = 0;

        if (flag == 0)
                lcd_rs = 1;                     // 表示データの場合
        else
                lcd_rs = 0;                     // コマンドデータの場合

        lcd_delay_us(1);                //1μsecウェイト
                
        lcd_stb = 1;                    // strobe(E) ON (Enable)
                        
        lcd_delay_us(1);                // 1μsec : strobe信号の幅

        lcd_stb = 0;                    // reset strobe
}

//////// 1文字表示関数
void lcd_data(char asci)
{
        lcd_out(asci, 0);               // 上位4ビット出力
        lcd_out(asci<<4, 0);    // 下位4ビット出力
        lcd_delay_us(50);               //50μsecウェイト
}

/////// コマンド出力関数
void lcd_cmd(char cmd)
{
        lcd_out(cmd, 1);                // 上位4ビット出力
        lcd_out(cmd<<4, 1);             // 下位4ビット出力
        if((cmd & 0x03) != 0)   // clear Homeの場合
        lcd_delay_ms(2);        //      2msec待ち
        else
        lcd_delay_us(50);       //50μsecウェイト    
}

/////// 全消去関数
void lcd_clear(void)
{
        lcd_cmd(0x01);                  // 初期化コマンド出力
}

/////// 文字列出力関数
void lcd_str(char* str)      
{
        while(*str)                             //文字列終端の '\0'を検出するまで
        {
                lcd_data(*str);         // 1文字表示
                str++;                          //ポインタをインクリメント                          
        }       
}


/////// 初期化関数
void lcd_init(void)
{
        lcd_delay_ms(20);               //20msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        lcd_delay_ms(5);                //5msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        lcd_delay_ms(1);                //1msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        lcd_delay_ms(1);                //1msecウェイト
        lcd_out(0x20, 1);               // 4bit mode set
        lcd_delay_ms(1);                //1msecウェイト
        lcd_cmd(0x2E);                  // DL=0 4bit mode
        lcd_cmd(0x08);                  // display off C=D=B=0
        lcd_cmd(0x0D);                  // display on C=D=1 B=0
        lcd_cmd(0x06);                  // entry I/D=1 S=0
        lcd_cmd(0x02);                  // cursor home
}




 
<実行結果>
 
PIC32MX795F512Lの液晶
上段: PCからの受信文字列
下段: PCへの返信文字列
PC画面
USB接続が
    未接続の状態
-
接続ボタンをクリックして
  USB接続が
    確立した状態
-
コンボボックスから
”U.K.”を選択して送信し、
返信をリストボックスに
     受信した状態
次に、コンボボックスから
”America”を選択して送信し、
返信をリストボックスに
     受信した状態
次に、コンボボックスから
”Japan”を選択して送信し、
返信をリストボックスに
     受信した状態
次に、コンボボックスから
”中国”を選択して送信し、
返信をリストボックスに
     受信した状態
最後に、コンボボックスから
”I am a boy”を選択して送信し、
返信をリストボックスに
     受信した状態


 


■ PIC32MX795F512L  HIDクラス 漢字を含む文字列の送受信(グラフィック液晶

PIC32MX795F512Lにグラフィック液晶を接続した USB通信 送受信の例を紹介します。   → PC側 VC++ ソフト

<試作品仕様>
 ・PC側からデータをPIC側にUSB HIDクラス通信で送信する。
 ・送信文字コードはシフトJISを使用する
 ・PIC側では受信した文字列を液晶上段に、受信データに基づき返信したデータを液晶下段に表示する。
 ・PC側でも受信したデータをリストボックスに表示する。
 ・PC側からの送信データ 及びPIC側からの返信データは以下とする。
     @ U.K.       →  London
     A America    →  Washington
     B Japan      →  0x938c(東)0x8b9e(京)
     C 中(0x9286)国 (0x8D91)   → 北(0x966B)京(0x8B9E)
     D I am a boy.   →  Pardon ?

<試作品回路図>(→回路図のPDFファイル




<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています

    

          

   <プログラム例>


#include "Main.h"
#include "GDD_Screens.h"

//USB関係
#include "./USB/usb.h"
#include "HardwareProfile.h"
#include "./USB/usb_function_hid.h"

#include "1lcd_lib_C32.h"

//システムクロック80MHz  ペリフェラルクロック60MHz
        #pragma config UPLLEN   = ON        // USB PLL Enabled
        #pragma config FPLLMUL  = MUL_15        // PLL Multiplier
        #pragma config UPLLIDIV = DIV_2         // USB PLL Input Divider
        #pragma config FPLLIDIV = DIV_2         // PLL Input Divider
        #pragma config FPLLODIV = DIV_1         // PLL Output Divider
        #pragma config FPBDIV   = DIV_1         // Peripheral Clock divisor
        #pragma config FWDTEN   = OFF           // Watchdog Timer
        #pragma config WDTPS    = PS1           // Watchdog Timer Postscale
        #pragma config FCKSM    = CSDCMD        // Clock Switching & Fail Safe Clock Monitor
        #pragma config OSCIOFNC = OFF           // CLKO Enable
        #pragma config POSCMOD  = HS            // Primary Oscillator
        #pragma config IESO     = OFF           // Internal/External Switch-over
        #pragma config FSOSCEN  = OFF           // Secondary Oscillator Enable (KLO was off)
        #pragma config FNOSC    = PRIPLL        // Oscillator Selection
        #pragma config CP       = OFF           // Code Protect
        #pragma config BWP      = OFF           // Boot Flash Write Protect
        #pragma config PWP      = OFF           // Program Flash Write Protect
        #pragma config ICESEL   = ICS_PGx2      // ICE/ICD Comm Channel Select


// Configuration bits
//    #pragma config FPLLODIV = DIV_1, FPLLMUL = MUL_20, FPLLIDIV = DIV_2, FWDTEN = OFF, FCKSM = CSECME, FPBDIV = DIV_1
//    #pragma config OSCIOFNC = ON, POSCMOD = XT, FSOSCEN = ON, FNOSC = PRIPLL
//    #pragma config CP = OFF, BWP = OFF, PWP = OFF


// SPI Device Initialization Function 
#if defined (USE_SST25VF016)
    #define FlashInit(pInitData) SST25Init((DRV_SPI_INIT_DATA*)pInitData)
    #if defined (SPI_CHANNEL_2_ENABLE)
        const DRV_SPI_INIT_DATA SPI_Init_Data = {SST25_SPI_CHANNEL, 1, 0, 0, 1, 1, 0};
    #endif
#endif

#define RX_DATA_BUFFER_ADDRESS
#define TX_DATA_BUFFER_ADDRESS

unsigned char ReceivedDataBuffer[64] RX_DATA_BUFFER_ADDRESS;
unsigned char ToSendDataBuffer[64] TX_DATA_BUFFER_ADDRESS;
unsigned char SendBuf[64];

unsigned char myChr[17];    //文字列部分

unsigned char tempBuf[1024];
unsigned char* str10;


char Buf[64];   //文字列のバッファー用レジスタ
volatile DWORD  tick = 0;      // tick counter
unsigned char* str1;


char* str2;

unsigned char Kaigyou[] = "\n";
unsigned char Japan[]   = "Japan           ";
unsigned char UK[]      = "U.K.            ";
unsigned char America[] = "America         ";
                                //unsigned char Chuugoku[] = "Chuugoku        ";
unsigned char Chuugoku[] = {0x92,0x86,0x8D,0x91,' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
                        //中[0x9286]  国[0x8D91]

char Tokyo_english[]      = "Tokyo           \r";
char Tokyo[]            = {0x93,0x8C,0x8B,0x9E,' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','\r'};
                                        //シフトJIS 東[938C]、京[8B9E]
char Pekin[]            = {0x96,0x6B,0x8B,0x9E,' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','\r'};
                            //シフトJIS  北[966B]、京[8B9E]
char Pekin_english[]    = "Pekin           \r";

char London[]           = "London          \r";
char Washington[]       = "Washington      \r";
char Pardon[]           = "Pardon ?        \r";



BOOL blinkStatusValid;
USB_HANDLE USBGenericOutHandle; //送信ハンドル
USB_HANDLE USBGenericInHandle;  //受信ハンドル



USB_HANDLE USBOutHandle = 0;    //USB handle.  Must be initialized to 0 at startup.
USB_HANDLE USBInHandle = 0;     //USB handle.  Must be initialized to 0 at startup.



  
// 関数のプロトタイプ宣言
void BlinkUSBStatus(void);
void ProcessIO(void);
void YourHighPriorityISRCode();
void YourLowPriorityISRCode();
void USBCBSendResume(void);


void            TickInit(void);                 // starts tick counter



void delay_us(unsigned int usec)        //1μsec遅延関数
{
        int count;

        count = (int)(Clock/20000000)*usec;

        do      //実測: at Clock=80000000
        {       //delay_us(1000)→1003μsec、 delay_us(100)→102μsec、delay_us(10)→11μsec、delay_us(1)→1.6μsec

                asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");
                asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");

                count--;
        }while(count != 0);
}

void delay_ms(unsigned int msec)        //1msec遅延関数
{
        unsigned int i;

        for(i=0; i<msec; i++)
        delay_us(1000);
}




int main(void)
{

     int i ;


    for(i = 0; i < 65; i++)Buf[i] = ' ';

    SYSTEMConfigPerformance(60000000);  //システム最適化



    INTEnableSystemMultiVectoredInt();                          //ベクタ方式割り込みを許可する
//    SYSTEMConfigPerformance(GetSystemClock());                //SYSTEMConfigPerformance(80000000);// システム最適化//キャッシュ・プリフェッチバッファ有効化
    DDPCONbits.JTAGEN = 0;      //I/OポートとしてRA0、RA1、RA4、RA5をつかう場合、電源投入後DDPCONレジスタのbit3を0に、設定する必要があり;ます。
    AD1PCFG =0xFFFF;    //★必須    //Bポート:アナログ → デジタル


    TRISBbits.TRISB15 = 0;       //キャラクタ液晶ポート設定
    TRISBbits.TRISB14 = 0;       //キャラクタ液晶ポート設定
    TRISBbits.TRISB13 = 0;       //キャラクタ液晶ポート設定
    TRISBbits.TRISB12 = 0;       //キャラクタ液晶ポート設定
    TRISAbits.TRISA9 = 0;       //キャラクタ液晶ポート設定
    TRISAbits.TRISA10 = 0;       //キャラクタ液晶ポート設定

    TRISGbits.TRISG15 = 0;      //RG15(1番ピン)ポート LED点灯用
    TRISDbits.TRISD2 = 0;       //RD2 LED点灯用
    TRISDbits.TRISD3 = 0;       //RD3 LED点灯用

    LATGbits.LATG15 = 1;    //LED off
    LATDbits.LATD2 = 1;     //LED off
    LATDbits.LATD3 = 1;     //LED off

    TRISBbits.TRISB0 = 1;   //RB0 in port
    TRISBbits.TRISB1 = 1;   //RB1 in port


        //USB関係
        USBDeviceInit();
        USBOutHandle = 0;
        USBInHandle = 0;
        blinkStatusValid = TRUE;
        USBDeviceAttach();


    lcd_init();                         // LCD初期化
    lcd_cmd(0b00001100);    // カーソル:OFF  ブリンク:OFF
  
    lcd_cmd(0x80);          //1目の先頭へ
    sprintf(Buf,"USB HID");//
    lcd_str(Buf);                   //液晶表示

    lcd_cmd(0xC0);          //2行目の先頭へ
    sprintf(Buf," GDDX LCD Start !!");  //
    lcd_str(Buf);           // 開始メッセージ1行目表示

    DisplayResetDisable();        //Sets RST high
    DisplayResetConfig();         //Sets the pin to output

    DelayMs(3000);                    //Wait 500 ms at startup

     SetColor(BLACK);
     ClearDevice();

    GOL_MSG msg;                        // GOL message structure to interact with GOL
    GOLInit();     // Initialize graphics library and create default style scheme for GOL

    //SPIフラッシュメモリ初期化    //Set IOs directions for SST25 SPI
    //SST25VF016がないと正常に表示されない
    //抵抗膜をPIのがADコンバータを使用して、タッチ位置を検出する場合は位置校正記憶のためSST25VF016は必要
    SST25_CS_LAT = 1;
    SST25_CS_TRIS = 0;
    SST25_SCK_TRIS = 0;
    SST25_SDO_TRIS = 0;
    SST25_SDI_TRIS = 1;
    FlashInit(&SPI_Init_Data);  // initialize the Flash Memory driver

    TouchHardwareInit();        //タッチパネル初期化
    TickInit();         //タイマ4 初期化

    str10 = &tempBuf[0];


    GDDDemoCreateFirstScreen();



    while(1)
    {

        // USB接続中なら送受信実行
        if((USBDeviceState >= CONFIGURED_STATE)&&(USBSuspendControl!=1))ProcessIO();

        if(GOLDraw())               // Draw GOL object
        {
            TouchGetMsg(&msg);      // Get message from touch screen

                        
            GOLMsg(&msg);           // Process message
        }
    }//end while
}

/////////////////////////////////////////////////////////////////////////////
// Function: WORD GOLMsgCallback(WORD objMsg, OBJ_HEADER* pObj, GOL_MSG* pMsg)
// Input: objMsg - translated message for the object,
//        pObj - pointer to the object,
//        pMsg - pointer to the non-translated, raw GOL message
// Output: if the function returns non-zero the message will be processed by default
// Overview: it's a user defined function. GOLMsg() function calls it each

//           time the valid message for the object received
/////////////////////////////////////////////////////////////////////////////
WORD GOLMsgCallback(WORD objMsg, OBJ_HEADER *pObj, GOL_MSG *pMsg)
{
    WORD    objectID;

    objectID = GetObjID(pObj);

    GDDDemoGOLMsgCallback(objMsg, pObj, pMsg);
    
    // Add additional code here...

    return (1);
}

/////////////////////////////////////////////////////////////////////////////
// Function: WORD GOLDrawCallback()
// Output: if the function returns non-zero the draw control will be passed to GOL
// Overview: it's a user defined function. GOLDraw() function calls it each
//           time when GOL objects drawing is completed. User drawing should be done here.
//           GOL will not change color, line type and clipping region settings while

//           this function returns zero.
/////////////////////////////////////////////////////////////////////////////
WORD GOLDrawCallback(void)
{
    GDDDemoGOLDrawCallback();

    // Add additional code here...

    return (1);
}




void  __ISR(_TIMER_4_VECTOR, ipl1) _T4Interrupt(void)   //タイマ4割り込み      //100msec毎
{
  //  LATGbits.LATG15 = 0;      //割り込み時間(実測):3msec

    tick++;
    TMR4 = 0;
    mT4ClearIntFlag();  // Clear flag
    TouchDetectPosition();
/*
    lcd_clear();            // 全消去

    lcd_cmd(0x80);          //1行目の先頭へ
    sprintf(Buf,"X = %d",TouchGetX());//タッチX座標表示
    lcd_str(Buf);                   //液晶表示

    lcd_cmd(0xC0);          //2行目の先頭へ
    sprintf(Buf,"Y = %d",TouchGetY());  //タッチY座標表示
    lcd_str(Buf);           // 開始メッセージ1行目表示

*/
//    LATGbits.LATG15 = 1;



}


//---------------------------------------------------------------------------------
#define SAMPLE_PERIOD       500 // us
#define TICK_PERIOD                     (GetPeripheralClock() * SAMPLE_PERIOD) / 4000000
//TICK_PERIOD = 80000000 * 500 / 4000000 = 80* 500 / 4 = 20*500 = 10000
void TickInit(void)     //タイマ4初期化
{
   OpenTimer4(T4_ON | T4_PS_1_256, 31249);      //1000/80000000*256*31249 =99.9968 msec
// OpenTimer4(T4_ON | T4_PS_1_8, 10000);        //2msec
// OpenTimer4(T4_ON | T4_PS_1_8, TICK_PERIOD);  //実測値:35μsec //オーバーフローエラー発生

    ConfigIntTimer4(T4_INT_ON | T4_INT_PRIOR_1);
}


void ProcessIO(void)
{
    int i;
    if(!HIDRxHandleBusy(USBOutHandle))
    {
        switch(ReceivedDataBuffer[0])   //コマンドの種類判定
        {
            //接続確認応答
            case 0x30: //
                SendBuf[2] = 'O';
                SendBuf[3] = 'K';
                if(!HIDTxHandleBusy(USBInHandle))
                USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&SendBuf[0],64);    //PC側に送信

                break;

            case 0x80:  //受信文字列判定   & 対応文字列返信

                for(i = 1; i < 17; i++)myChr[i-1] = ReceivedDataBuffer[i];

                str1 = &myChr[0];
            //    str1 = &ReceivedDataBuffer[0];

                if(strcmp(str1,Japan) == 0)
                {

                        lcd_cmd(0x80);  //1行目へ
                        sprintf(Buf,"%s",str1);
                        lcd_str(Buf);       //受信データを液晶に表示
                        lcd_cmd(0xC0);  //2行目
                        sprintf(Buf,"%x%x%x%x",Tokyo[0],Tokyo[1],Tokyo[2],Tokyo[3]);
                                                        //sprintf()のバグのため(?)か C18では制御文字の前にffをつける仕様になっているためか
                                                        //液晶には ”ff93ff8Cff8Bff9E” と表示される
                                                        //シフトJIS 東[938C]、京[8B9E]
                        lcd_str(Buf);       //送信データを液晶に表示

                        sprintf(Buf,"%c%c%c%c",Tokyo[0],Tokyo[1],Tokyo[2],Tokyo[3]);    //送信するときは%cにして送信

                        str2 = Tokyo_english;
                }
                else if((myChr[0] == Chuugoku[0]) && (myChr[1] == Chuugoku[1]) && (myChr[2] == Chuugoku[2]) && (myChr[3] == Chuugoku[3]) &&
                        (myChr[4] == Chuugoku[4]) && (myChr[5] == Chuugoku[5]) && (myChr[6] == Chuugoku[6]) && (myChr[7] == Chuugoku[7]) &&
                        (myChr[8] == Chuugoku[8]) && (myChr[9] == Chuugoku[9]) && (myChr[10] == Chuugoku[10]) && (myChr[11] == Chuugoku[11]) &&
                        (myChr[12] == Chuugoku[12]) && (myChr[13] == Chuugoku[13]) && (myChr[14] == Chuugoku[14]) && (myChr[15] == Chuugoku[15]))
         //       else if(strcmp(str1,Chuugoku) == 0)   //NG: strcmp( )はASCII文字のみに対応 制御文字には対応していない
                {
                      lcd_cmd(0x80);  //1行目へ
                        sprintf(Buf,"%s",str1);
                        lcd_str(Buf);       //受信データを液晶に表示
                        lcd_cmd(0xC0);  //2行目
                        sprintf(Buf,"%x%x%x%x",Pekin[0],Pekin[1],Pekin[2],Pekin[3]);
                                                        //sprintf()のバグのため(?)か C18では制御文字の前にffをつける仕様になっているためか
                                                        //液晶には ”ff93ff8Cff8Bff9E” と表示される
                                                        //シフトJIS 東[938C]、京[8B9E]
                        lcd_str(Buf);       //送信データを液晶に表示

                        sprintf(Buf,"%c%c%c%c",Pekin[0],Pekin[1],Pekin[2],Pekin[3]);    //送信するときは%cにして送信
                        
                        str2 = Pekin_english;



                }
                else if(strcmp(str1,UK) == 0)
                {
                        str2 = London;
                        lcd_cmd(0x80);  //1行目へ
                        sprintf(Buf,"%s",str1);
                        lcd_str(Buf);       //受信データを液晶に表示
                        lcd_cmd(0xC0);  //2行目
                        sprintf(Buf,"%s",str2);
                        lcd_str(Buf);       //送信データを液晶に表示


                }
                else if(strcmp(str1,America) == 0)
                {
                        str2 = Washington;
                        lcd_cmd(0x80);  //1行目へ
                        sprintf(Buf,"%s",str1);
                        lcd_str(Buf);       //受信データを液晶に表示
                        lcd_cmd(0xC0);  //2行目
                        sprintf(Buf,"%s",str2);
                        lcd_str(Buf);       //送信データを液晶に表示
                }
                else
                {
                        str2 = Pardon;
                        lcd_cmd(0x80);  //1行目へ
                        sprintf(Buf,"%s",str1);
                        lcd_str(Buf);       //受信データを液晶に表示
                        lcd_cmd(0xC0);  //2行目
                        sprintf(Buf,"%s",str2);
                        lcd_str(Buf);       //送信データを液晶に表示
                }

                                       //グラフィック液晶のStatic Text Widgetに表示
                        STATICTEXT *pSTE_1 = (STATICTEXT*)GOLFindObject(STE_1);    //エディットボックスのオブジェクト検出

                        pSTE_1->hdr.state = ST_DRAW;    //再描画により文字は左アラインにリセットされる

                       strncat(str10,str2,16);      //文字追加
                       strncat(str10,Kaigyou,16);   //改行
                      
                       StSetText((STATICTEXT*)pSTE_1, str10);    //
                       SetState(pSTE_1, ST_DRAW);

                       for(i = 0; i < 18; i++)SendBuf[i] = Buf[i]; //送信データセット




                if(!HIDTxHandleBusy(USBInHandle))
                USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&SendBuf[0],64);    //PC側に送信
                break;

        }

        //次の受信実行
        USBOutHandle = HIDRxPacket(HID_EP, (BYTE*)&ReceivedDataBuffer, 64);
    }
}





// ******************************************************************************************************
// ************** USB Callback Functions ****************************************************************
// ******************************************************************************************************

void USBCBSuspend(void)
{
}

void USBCBWakeFromSuspend(void)
{
}

void USBCB_SOF_Handler(void)
{
}
void USBCBErrorHandler(void)
{
}
void USBCBCheckOtherReq(void)
{
    USBCheckHIDRequest();
}
void USBCBStdSetDscHandler(void)
{
}
void USBCBInitEP(void)
{
    //enable the HID endpoint
    USBEnableEndpoint(HID_EP,USB_IN_ENABLED|USB_OUT_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
    //Re-arm the OUT endpoint for the next packet
    USBOutHandle = HIDRxPacket(HID_EP,(BYTE*)&ReceivedDataBuffer,64);
}

void USBCBSendResume(void)
{
    static WORD delay_count;
    if(USBGetRemoteWakeupStatus() == TRUE)
    {
        if(USBIsBusSuspended() == TRUE)
        {
            USBMaskInterrupts();

            //Clock switch to settings consistent with normal USB operation.
            USBCBWakeFromSuspend();
            USBSuspendControl = 0;
            USBBusIsSuspended = FALSE;  //So we don't execute this code again,
                                        //until a new suspend condition is detected.
            delay_count = 3600U;
            do
            {
                delay_count--;
            }while(delay_count);

            //Now drive the resume K-state signalling onto the USB bus.
            USBResumeControl = 1;       // Start RESUME signaling
            delay_count = 1800U;        // Set RESUME line for 1-13 ms
            do
            {
                delay_count--;
            }while(delay_count);
            USBResumeControl = 0;       //Finished driving resume signalling

            USBUnmaskInterrupts();
        }
    }
}
BOOL USER_USB_CALLBACK_EVENT_HANDLER(int event, void *pdata, WORD size)
{
    switch(event)
    {
        case EVENT_TRANSFER:
            //Add application specific callback task or callback function here if desired.
            break;
        case EVENT_SOF:
            USBCB_SOF_Handler();
            break;
        case EVENT_SUSPEND:
            USBCBSuspend();
            break;
        case EVENT_RESUME:
            USBCBWakeFromSuspend();
            break;
        case EVENT_CONFIGURED:
            USBCBInitEP();
            break;
        case EVENT_SET_DESCRIPTOR:
            USBCBStdSetDscHandler();
            break;
        case EVENT_EP0_REQUEST:
            USBCBCheckOtherReq();
            break;
        case EVENT_BUS_ERROR:
            USBCBErrorHandler();
            break;
        case EVENT_TRANSFER_TERMINATED:
            break;
        default:
            break;
    }
    return TRUE;
}

 //------------------------------------------------------------------------------
//usb_descriptors.c

/* Device Descriptor */
ROM USB_DEVICE_DESCRIPTOR device_dsc=
{
    0x12,    // Size of this descriptor in bytes
    USB_DESCRIPTOR_DEVICE,                // DEVICE descriptor type
    0x0200,                 // USB Spec Release Number in BCD format
    0x00,                   // Class Code
    0x00,                   // Subclass code
    0x00,                   // Protocol code
    USB_EP0_BUFF_SIZE,          // Max packet size for EP0, see usb_config.h
    0x04D8,                 // Vendor ID
    0x003F,                 // Product ID: Custom HID device demo
    0x0002,                 // Device release number in BCD format
    0x01,                   // Manufacturer string index
    0x02,                   // Product string index
    0x00,                   // Device serial number string index
    0x01                    // Number of possible configurations
};

/* Configuration 1 Descriptor */
ROM BYTE configDescriptor1[]={
    /* Configuration Descriptor */
    0x09,//sizeof(USB_CFG_DSC),    // Size of this descriptor in bytes
    USB_DESCRIPTOR_CONFIGURATION,                // CONFIGURATION descriptor type
    0x29,0x00,            // Total length of data for this cfg
    1,                      // Number of interfaces in this cfg
    1,                      // Index value of this configuration
    0,                      // Configuration string index
    _DEFAULT | _SELF,               // Attributes, see usb_device.h
    50,                     // Max power consumption (2X mA)
                                                        
    /* Interface Descriptor */
    0x09,//sizeof(USB_INTF_DSC),   // Size of this descriptor in bytes
    USB_DESCRIPTOR_INTERFACE,               // INTERFACE descriptor type
    0,                      // Interface Number
    0,                      // Alternate Setting Number
    2,                      // Number of endpoints in this intf
    HID_INTF,               // Class code
    0,     // Subclass code
    0,     // Protocol code
    0,                      // Interface string index

    /* HID Class-Specific Descriptor */
    0x09,//sizeof(USB_HID_DSC)+3,    // Size of this descriptor in bytes
    DSC_HID,                // HID descriptor type
    0x11,0x01,                 // HID Spec Release Number in BCD format (1.11)
    0x00,                   // Country Code (0x00 for Not supported)
    HID_NUM_OF_DSC,         // Number of class descriptors, see usbcfg.h
    DSC_RPT,                // Report descriptor type
    HID_RPT01_SIZE,0x00,//sizeof(hid_rpt01),      // Size of the report descriptor
    
    /* Endpoint Descriptor */
    0x07,/*sizeof(USB_EP_DSC)*/
    USB_DESCRIPTOR_ENDPOINT,    //Endpoint Descriptor
    HID_EP | _EP_IN,                   //EndpointAddress
    _INTERRUPT,                       //Attributes
    0x40,0x00,                  //size
    0x01,                        //Interval

    /* Endpoint Descriptor */
    0x07,/*sizeof(USB_EP_DSC)*/
    USB_DESCRIPTOR_ENDPOINT,    //Endpoint Descriptor
    HID_EP | _EP_OUT,                   //EndpointAddress
    _INTERRUPT,                       //Attributes
    0x40,0x00,                  //size
    0x01                        //Interval
};

//Language code string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[1];}sd000={
sizeof(sd000),USB_DESCRIPTOR_STRING,{0x0409
}};

//Manufacturer string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[25];}sd001={
sizeof(sd001),USB_DESCRIPTOR_STRING,
{'M','i','c','r','o','c','h','i','p',' ',
'T','e','c','h','n','o','l','o','g','y',' ','I','n','c','.'
}};

//Product string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[22];}sd002={
sizeof(sd002),USB_DESCRIPTOR_STRING,
{'S','i','m','p','l','e',' ','H','I','D',' ',
'D','e','v','i','c','e',' ','D','e','m','o'
}};

//Class specific descriptor - HID 
ROM struct{BYTE report[HID_RPT01_SIZE];}hid_rpt01={
{
    0x06, 0x00, 0xFF,       // Usage Page = 0xFF00 (Vendor Defined Page 1)
    0x09, 0x01,             // Usage (Vendor Usage 1)
    0xA1, 0x01,             // Collection (Application)
    0x19, 0x01,             //      Usage Minimum 
    0x29, 0x40,             //      Usage Maximum       //64 input usages total (0x01 to 0x40)
    0x15, 0x01,             //      Logical Minimum (data bytes in the report may have minimum value = 0x00)
    0x25, 0x40,                 //      Logical Maximum (data bytes in the report may have maximum value = 0x00FF = unsigned 255)
    0x75, 0x08,             //      Report Size: 8-bit field size
    0x95, 0x40,             //      Report Count: Make sixty-four 8-bit fields (the next time the parser hits an "Input", "Output", or "Feature" item)
    0x81, 0x00,             //      Input (Data, Array, Abs): Instantiates input packet fields based on the above report size, count, logical min/max, and usage.
    0x19, 0x01,             //      Usage Minimum 
    0x29, 0x40,             //      Usage Maximum       //64 output usages total (0x01 to 0x40)
    0x91, 0x00,             //      Output (Data, Array, Abs): Instantiates output packet fields.  Uses same report size and count as "Input" fields, since nothing new/different was specified to the parser since the "Input" item.
    0xC0}                   // End Collection
};                  


//Array of configuration descriptors
ROM BYTE *ROM USB_CD_Ptr[]=
{
    (ROM BYTE *ROM)&configDescriptor1
};

//Array of string descriptors
ROM BYTE *ROM USB_SD_Ptr[]=
{
    (ROM BYTE *ROM)&sd000,
    (ROM BYTE *ROM)&sd001,
    (ROM BYTE *ROM)&sd002
};

/** EOF usb_descriptors.c ***************************************************/

#endif


//*************************************************************************
//インクルードファイル    1lcd_lib_C32.h
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C32コンパイラ対応等で変更したものです。
//*************************************************************************

#include <proc/p32mx795f512l.h>         //PIC32MX460F512L

#define Clock   80000000        // 単位はHzで指定


// LCDポート設定
#define lcd_port_DB7    LATBbits.LATB15 //LCDのDB7(14番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB6    LATBbits.LATB14 //LCDのDB6(13番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB5    LATBbits.LATB13 //のDB5(12番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB4    LATBbits.LATB12 //LCDのDB4(11番ピン)に接続されつPIC側ポート番号設定
#define lcd_rs                  LATAbits.LATA9  //LCDのrs(4番ピン)に接続されるPIC側ポート番号設定
#define lcd_stb                 LATAbits.LATA10 //LCDのstb(6番ピン)に接続されるPIC側ポート番号設定



void lcd_out(char code, char flag);
void lcd_data(char asci);
void lcd_cmd(char cmd);
void lcd_clear(void);
void lcd_init(void);
void lcd_str(char *str);



//**************************************************************************
//インクルードファイル    1lcd_lib_C32.c
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C32コンパイラ対応等で変更したものです。
//**************************************************************************

///////////////////////////////////////////////
//  液晶表示器制御ライブラリ for C32コンパイラー
//  内蔵関数は以下
//    lcd_init()    ----- 初期化
//    lcd_cmd(cmd)  ----- コマンド出力
//    lcd_data(chr) ----- 1文字表示出力
//    lcd_clear()   ----- 全消去
//    lcd_str(str*) ----- 文字列表示 
//////////////////////////////////////////////

#include        "1lcd_lib_C32.h"

void lcd_delay_us(unsigned int usec)    //1μsec遅延関数
{
        int count;

        count = (int)(Clock/20000000)*usec;
        do
        {
                asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");
                asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");
                count--;        
        }while(count != 0);
}

void lcd_delay_ms(unsigned int msec)    //1msec遅延関数
{
        unsigned int i;
        
        for(i=0; i<msec; i++)
        lcd_delay_us(1000);
}


//////// データ出力サブ関数
void lcd_out(char code, char flag)
{
        if(code & 0b10000000)lcd_port_DB7 = 1;  //LCDのDB7への出力セット
        else lcd_port_DB7 = 0;
        if(code & 0b01000000)lcd_port_DB6 = 1;  //LCDのDB6への出力セット
        else lcd_port_DB6 = 0;
        if(code & 0b00100000)lcd_port_DB5 = 1;  //LCDのDB5への出力セット
        else lcd_port_DB5 = 0;
        if(code & 0b00010000)lcd_port_DB4 = 1;  //LCDのDB4への出力セット
        else lcd_port_DB4 = 0;

        if (flag == 0)
                lcd_rs = 1;                     // 表示データの場合
        else
                lcd_rs = 0;                     // コマンドデータの場合

        lcd_delay_us(1);                //1μsecウェイト
                
        lcd_stb = 1;                    // strobe(E) ON (Enable)
                        
        lcd_delay_us(1);                // 1μsec : strobe信号の幅

        lcd_stb = 0;                    // reset strobe
}

//////// 1文字表示関数
void lcd_data(char asci)
{
        lcd_out(asci, 0);               // 上位4ビット出力
        lcd_out(asci<<4, 0);    // 下位4ビット出力
        lcd_delay_us(50);               //50μsecウェイト
}

/////// コマンド出力関数
void lcd_cmd(char cmd)
{
        lcd_out(cmd, 1);                // 上位4ビット出力
        lcd_out(cmd<<4, 1);             // 下位4ビット出力
        if((cmd & 0x03) != 0)   // clear Homeの場合
        lcd_delay_ms(2);        //      2msec待ち
        else
        lcd_delay_us(50);       //50μsecウェイト    
}

/////// 全消去関数
void lcd_clear(void)
{
        lcd_cmd(0x01);                  // 初期化コマンド出力
}

/////// 文字列出力関数
void lcd_str(char* str)      
{
        while(*str)                             //文字列終端の '\0'を検出するまで
        {
                lcd_data(*str);         // 1文字表示
                str++;                          //ポインタをインクリメント                          
        }       
}


/////// 初期化関数
void lcd_init(void)
{
        lcd_delay_ms(20);               //20msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        lcd_delay_ms(5);                //5msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        lcd_delay_ms(1);                //1msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        lcd_delay_ms(1);                //1msecウェイト
        lcd_out(0x20, 1);               // 4bit mode set
        lcd_delay_ms(1);                //1msecウェイト
        lcd_cmd(0x2E);                  // DL=0 4bit mode
        lcd_cmd(0x08);                  // display off C=D=B=0
        lcd_cmd(0x0D);                  // display on C=D=1 B=0
        lcd_cmd(0x06);                  // entry I/D=1 S=0
        lcd_cmd(0x02);                  // cursor home
}
}

 

//その他 FAT、グラフィックライブラリ関連のインクルードファイルは下記にあります。
//マイクロチップのライブラリダウンロードページ: Microchip Libraries for Applications  私がつかったバージョンは \microchip_solutions_v2013-02-15 です。
//GDDX関連のファイルは Microchip Graphics Display Designer X からダウンロードできます。 私がつかったバージョンは GDDX v.1.10 です
//グラフィック液晶INT035TFTの関連情報は Displaytechのホームページ 及び DisplaytechのForum  にあります。
<実行結果>
 
PIC32MX795F512Lのグラフィック液晶
上段: PCからの受信文字列
下段: PCへの返信文字列
PC画面
USB接続が
    未接続の状態
-
接続ボタンをクリックして
  USB接続が
    確立した状態
-
コンボボックスから
”U.K.”を選択して送信し、
返信をリストボックスに
     受信した状態
次に、コンボボックスから
”America”を選択して送信し、
返信をリストボックスに
     受信した状態
次に、コンボボックスから
”Japan”を選択して送信し、
返信をリストボックスに
     受信した状態
次に、コンボボックスから
”中国”を選択して送信し、
返信をリストボックスに
     受信した状態
最後に、コンボボックスから
”I am a boy”を選択して送信し、
返信をリストボックスに
     受信した状態

■ PIC32MX795F512L  <HIDクラス・ホストモード> グラフィック液晶 ASSCII文字簡易エディタ

 グラフィック液晶付PIC32MX795F512Lに USBコネクタの市販キーボードを接続した場合の 簡単なエディタを作ったので紹介します。
<試作品仕様>
 ・PIC32MX795F512Lにグラフィック液晶を8080 16ビットパラレルで接続する
 ・市販の日本語109キーボードを接続して キーボードから打鍵して文字と記号をグラフィック液晶に表示する
 ・グラフィックでの文字にはマイクロチップのGDDXのStatic Text ウィジェットを用いる
 ・表示の他に エンターキーでの改行 及びバックスペースキーとデリートキーでの文字消去ができること

<試作品回路図>(→回路図のPDFファイル

    

<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています


          

   <プログラム例>



//Main( ).c


#include "Main.h"
#include "GDD_Screens.h"

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "GenericTypeDefs.h"
#include "HardwareProfile.h"
#include "usb_config.h"

#include "USB/usb.h"
#include "USB/usb_host_hid_parser.h"
#include "USB/usb_host_hid.h"
#include "1lcd_lib_C32.h"

#define STOP_TIMER_IN_IDLE_MODE     0x2000
#define TIMER_SOURCE_INTERNAL       0x0000
#define TIMER_ON                    0x8000
#define GATED_TIME_DISABLED         0x0000
#define TIMER_16BIT_MODE            0x0000

#define TIMER_PRESCALER_1           0x0000
#define TIMER_PRESCALER_8           0x0010
#define TIMER_PRESCALER_64          0x0020
#define TIMER_PRESCALER_256         0x0030
#define TIMER_INTERRUPT_PRIORITY    0x0001




// Configuration bits
    #pragma config FPLLODIV = DIV_1, FPLLMUL = MUL_20, FPLLIDIV = DIV_2, FWDTEN = OFF, FCKSM = CSECME, FPBDIV = DIV_1
    #pragma config OSCIOFNC = ON, POSCMOD = XT, FSOSCEN = ON, FNOSC = PRIPLL
    #pragma config CP = OFF, BWP = OFF, PWP = OFF

    #pragma config UPLLEN   = ON            // USB PLL Enabled
    #pragma config UPLLIDIV = DIV_2         // USB PLL Input Divider

typedef enum _APP_STATE
{
    DEVICE_NOT_CONNECTED,
    DEVICE_CONNECTED, /* Device Enumerated  - Report Descriptor Parsed */
    READY_TO_TX_RX_REPORT,
    GET_INPUT_REPORT, /* perform operation on received report */
    INPUT_REPORT_PENDING,
    SEND_OUTPUT_REPORT, /* Not needed in case of mouse */
    OUTPUT_REPORT_PENDING,
    ERROR_REPORTED
} APP_STATE;

typedef struct _HID_REPORT_BUFFER
{
    WORD  Report_ID;
    WORD  ReportSize;
    BYTE* ReportData;
    WORD  ReportPollRate;
}   HID_REPORT_BUFFER;

typedef struct _HID_LED_REPORT_BUFFER
{
    BYTE  NUM_LOCK      : 1;
    BYTE  CAPS_LOCK     : 1;
    BYTE  SCROLL_LOCK   : 1;
    BYTE  UNUSED        : 5;
}   HID_LED_REPORT_BUFFER;

#define MAX_ALLOWED_CURRENT             (500)         // Maximum power we can supply in mA
#define MINIMUM_POLL_INTERVAL           (0x0A)        // Minimum Polling rate for HID reports is 10ms

#define USAGE_PAGE_LEDS                 (0x08)

#define USAGE_PAGE_KEY_CODES            (0x07)
#define USAGE_MIN_MODIFIER_KEY          (0xE0)
#define USAGE_MAX_MODIFIER_KEY          (0xE7)

#define USAGE_MIN_NORMAL_KEY            (0x00)
#define USAGE_MAX_NORMAL_KEY            (0xFF)

/* Array index for modifier keys */
#define MODIFIER_LEFT_CONTROL           (0)
#define MODIFIER_LEFT_SHIFT             (1)
#define MODIFIER_LEFT_ALT               (2)
#define MODIFIER_LEFT_GUI               (3)
#define MODIFIER_RIGHT_CONTROL          (4)
#define MODIFIER_RIGHT_SHIFT            (5)
#define MODIFIER_RIGHT_ALT              (6)
#define MODIFIER_RIGHT_GUI              (7)

#define HID_CAPS_LOCK_VAL               (0x39)
#define HID_NUM_LOCK_VAL                (0x53)

#define MAX_ERROR_COUNTER               (10)


#define LCD_LINE_ONE                    (1)
#define LCD_LINE_TWO                    (2)

//  macros to identify special charaters(other than Digits and Alphabets)
#define Symbol_Exclamation              (0x1E)
#define Symbol_AT                       (0x1F)
#define Symbol_Pound                    (0x20)
#define Symbol_Dollar                   (0x21)
#define Symbol_Percentage               (0x22)
#define Symbol_Cap                      (0x23)
#define Symbol_AND                      (0x24)
#define Symbol_Star                     (0x25)
#define Symbol_NormalBracketOpen        (0x26)
#define Symbol_NormalBracketClose       (0x27)

#define Symbol_Return                   (0x28)
#define Symbol_Escape                   (0x29)
#define Symbol_Backspace                (0x2A)
#define Symbol_Tab                      (0x2B)
#define Symbol_Space                    (0x2C)
#define Symbol_HyphenUnderscore         (0x2D)
#define Symbol_EqualAdd                 (0x2E)
#define Symbol_BracketOpen              (0x2F)
#define Symbol_BracketClose             (0x30)
#define Symbol_BackslashOR              (0x31)
#define Symbol_SemiColon                (0x33)
#define Symbol_InvertedComma            (0x34)
#define Symbol_Tilde                    (0x35)      //109キーボードの漢字・全角/半角キーとバティングしている
#define Symbol_CommaLessThan            (0x36)
#define Symbol_PeriodGreaterThan        (0x37)
#define Symbol_FrontSlashQuestion       (0x38)

#define Symbol_Kanji                    (0x35)
#define Symbol_ScrLK                    (0x47)
#define Symbol_PrintScr                 (0x46)
#define Symbol_Delete                   (0x4C)
#define Symbol_PauseBreak               (0x48)


//
APP_STATE App_State_Keyboard = DEVICE_NOT_CONNECTED;

HID_DATA_DETAILS Appl_LED_Indicator;


HID_DATA_DETAILS Appl_ModifierKeysDetails;
HID_DATA_DETAILS Appl_NormalKeysDetails;

HID_USER_DATA_SIZE Appl_BufferModifierKeys[8];
HID_USER_DATA_SIZE Appl_BufferNormalKeys[6];
HID_USER_DATA_SIZE Appl_ShadowBuffer1[6];

HID_REPORT_BUFFER     Appl_raw_report_buffer;
HID_LED_REPORT_BUFFER Appl_led_report_buffer;

BYTE ErrorDriver;
BYTE ErrorCounter;
BYTE NumOfBytesRcvd;

BOOL ReportBufferUpdated;
BOOL LED_Key_Pressed = FALSE;
BOOL DisplayConnectOnce = FALSE;
BOOL DisplayDeatachOnce = FALSE;
BYTE CAPS_Lock_Pressed = 0;
BYTE NUM_Lock_Pressed = 0;
BYTE HeldKeyCount = 0;
BYTE HeldKey;

BYTE currCharPos;
BYTE FirstKeyPressed ;



// SPI Device Initialization Function 
#if defined (USE_SST25VF016)
    #define FlashInit(pInitData) SST25Init((DRV_SPI_INIT_DATA*)pInitData)
    #if defined (SPI_CHANNEL_2_ENABLE)
        const DRV_SPI_INIT_DATA SPI_Init_Data = {SST25_SPI_CHANNEL, 1, 0, 0, 1, 1, 0};
    #endif
#endif




BYTE App_HID2ASCII(BYTE a); //convert USB HID code (buffer[2 to 7]) to ASCII code
void AppInitialize(void);
BOOL AppGetParsedReportDetails(void);
void App_Detect_Device(void);
void App_ProcessInputReport(void);
void App_PrepareOutputReport(void);
void InitializeTimer(void);
void App_Clear_Data_Buffer(void);
BOOL App_CompareKeyPressedPrevBuf(BYTE data);
void App_CopyToShadowBuffer(void);
BOOL USB_HID_DataCollectionHandler(void);
void LCD_Display_Routine(BYTE data, BYTE HIDData);

void ProcessIO(void);


char Buf[65];   //文字列のバッファー用レジスタ
volatile DWORD  tick = 0;      // tick counter
 int myMode = 0;
 int GLcdLineNum = 0;  //グラフィック液晶の行数

 unsigned char Kaigyou[] = "\n";
 unsigned char tempBuf[1024];
unsigned char* myAllChar;
unsigned char tempBuf2[1024];
unsigned char* str20;


 int myLineNum = 0; //エディタの書込み行番号(0-12)
 int myColumnNum = -1;  //表示する文字の列番号
 int myCharPos = 0;    //

 int myColumnNum0 = 30;

  
// 関数のプロトタイプ宣言
void            TickInit(void);                 // starts tick counter



//------------------------------------------------------------------------------
void delay_us(unsigned int usec)        //1μsec遅延関数
{
        int count;
        count = (int)(Clock/20000000)*usec;
        do      //実測: at Clock=80000000
        {       //delay_us(1000)→1003μsec、 delay_us(100)→102μsec、delay_us(10)→11μsec、delay_us(1)→1.6μsec
                asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");
                asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");     asm("NOP");
                count--;
        }while(count != 0);
}

//------------------------------------------------------------------------------
void delay_ms(unsigned int msec)        //1msec遅延関数
{
        unsigned int i;

        for(i=0; i<msec; i++)
        delay_us(1000);
}



int main(void)
{
    INTEnableSystemMultiVectoredInt();                          //ベクタ方式割り込みを許可する
    SYSTEMConfigPerformance(GetSystemClock());          //SYSTEMConfigPerformance(80000000);// システム最適化//キャッシュ・プリフェッチバッファ有効化
    DDPCONbits.JTAGEN = 0;      //I/OポートとしてRA0、RA1、RA4、RA5をつかう場合、電源投入後DDPCONレジスタのbit3を0に、設定する必要があり;ます。
    SYSTEMConfigWaitStatesAndPB( GetSystemClock() );    //フラッシュメモリとPBCLKデバイダを指定したクロックで最適な状態に自動的に設定
    CheKseg0CacheOn();   // Enable the cache for the best performance




    AD1PCFG =0xFFFF;    //★必須    //Bポート:アナログ → デジタル


    TRISBbits.TRISB15 = 0;       //キャラクタ液晶ポート設定
    TRISBbits.TRISB14 = 0;       //キャラクタ液晶ポート設定
    TRISBbits.TRISB13 = 0;       //キャラクタ液晶ポート設定
    TRISBbits.TRISB12 = 0;       //キャラクタ液晶ポート設定
    TRISAbits.TRISA9 = 0;       //キャラクタ液晶ポート設定
    TRISAbits.TRISA10 = 0;       //キャラクタ液晶ポート設定

    TRISGbits.TRISG15 = 0;      //RG15(1番ピン)ポート LED点灯用
    TRISDbits.TRISD2 = 0;       //RD2 LED点灯用
    TRISDbits.TRISD3 = 0;       //RD3 LED点灯用

    LATGbits.LATG15 = 1;    //LED off
    LATDbits.LATD2 = 1;     //LED off
    LATDbits.LATD3 = 1;     //LED off

    TRISBbits.TRISB0 = 1;   //RB0 in port
    TRISBbits.TRISB1 = 1;   //RB1 in port






    lcd_init();                         // LCD初期化
    lcd_cmd(0b00001100);    // カーソル:OFF  ブリンク:OFF

    lcd_clear();
  
    lcd_cmd(0x80);          //1目の先頭へ
    sprintf(Buf,"USB & Touchi");//
    lcd_str(Buf);                   //液晶表示

    lcd_cmd(0xC0);          //2行目の先頭へ
    sprintf(Buf,"    Start !!");        //
    lcd_str(Buf);           // 開始メッセージ1行目表示

    DisplayResetDisable();        //Sets RST high
    DisplayResetConfig();         //Sets the pin to output

    DelayMs(3000);                    //Wait 500 ms at startup

     SetColor(BLACK);
     ClearDevice();


    GOL_MSG msg;                        // GOL message structure to interact with GOL
    GOLInit();     // Initialize graphics library and create default style scheme for GOL

    //SPIフラッシュメモリ初期化    //Set IOs directions for SST25 SPI
    //SST25VF016がないと正常に表示されない
    //抵抗膜をPIのがADコンバータを使用して、タッチ位置を検出する場合は位置校正記憶のためSST25VF016は必要
    SST25_CS_LAT = 1;
    SST25_CS_TRIS = 0;
    SST25_SCK_TRIS = 0;
    SST25_SDO_TRIS = 0;
    SST25_SDI_TRIS = 1;
    FlashInit(&SPI_Init_Data);  // initialize the Flash Memory driver

    USBInitialize(0);   //USBイニシャライズ
    TouchHardwareInit();        //タッチパネル初期化
    TickInit();         //タイマ4 初期化


    GDDDemoCreateFirstScreen();


    myAllChar = &tempBuf[0];
    str20 = &tempBuf2[0];


    while(1)
    {
        USBTasks();
        ProcessIO();

        if(GOLDraw())               // Draw GOL object
        {
            TouchGetMsg(&msg);      // Get message from touch screen
            GOLMsg(&msg);           // Process message
        }
    }//end while
}

/////////////////////////////////////////////////////////////////////////////
// Function: WORD GOLMsgCallback(WORD objMsg, OBJ_HEADER* pObj, GOL_MSG* pMsg)
// Input: objMsg - translated message for the object,
//        pObj - pointer to the object,
//        pMsg - pointer to the non-translated, raw GOL message
// Output: if the function returns non-zero the message will be processed by default
// Overview: it's a user defined function. GOLMsg() function calls it each

//           time the valid message for the object received
/////////////////////////////////////////////////////////////////////////////
WORD GOLMsgCallback(WORD objMsg, OBJ_HEADER *pObj, GOL_MSG *pMsg)
{
    WORD    objectID;

    objectID = GetObjID(pObj);

    GDDDemoGOLMsgCallback(objMsg, pObj, pMsg);
    
    // Add additional code here...

    return (1);
}

/////////////////////////////////////////////////////////////////////////////
// Function: WORD GOLDrawCallback()
// Output: if the function returns non-zero the draw control will be passed to GOL
// Overview: it's a user defined function. GOLDraw() function calls it each
//           time when GOL objects drawing is completed. User drawing should be done here.
//           GOL will not change color, line type and clipping region settings while

//           this function returns zero.
/////////////////////////////////////////////////////////////////////////////
WORD GOLDrawCallback(void)
{
    GDDDemoGOLDrawCallback();

    // Add additional code here...

    return (1);
}




void  __ISR(_TIMER_4_VECTOR, ipl1) _T4Interrupt(void)   //タイマ4割り込み      //100msec毎
{
  //  LATGbits.LATG15 = 0;      //割り込み時間(実測):3msec

    tick++;
    TMR4 = 0;
    mT4ClearIntFlag();  // Clear flag
    TouchDetectPosition();
/*
    lcd_clear();            // 全消去

    lcd_cmd(0x80);          //1行目の先頭へ
    sprintf(Buf,"X = %d",TouchGetX());//タッチX座標表示
    lcd_str(Buf);                   //液晶表示

    lcd_cmd(0xC0);          //2行目の先頭へ
    sprintf(Buf,"Y = %d",TouchGetY());  //タッチY座標表示
    lcd_str(Buf);           // 開始メッセージ1行目表示

*/
//    LATGbits.LATG15 = 1;



}


//---------------------------------------------------------------------------------
#define SAMPLE_PERIOD       500 // us
#define TICK_PERIOD                     (GetPeripheralClock() * SAMPLE_PERIOD) / 4000000
//TICK_PERIOD = 80000000 * 500 / 4000000 = 80* 500 / 4 = 20*500 = 10000
void TickInit(void)     //タイマ4初期化
{
   OpenTimer4(T4_ON | T4_PS_1_256, 31249);      //1000/80000000*256*31249 =99.9968 msec
// OpenTimer4(T4_ON | T4_PS_1_8, 10000);        //2msec
// OpenTimer4(T4_ON | T4_PS_1_8, TICK_PERIOD);  //実測値:35μsec //オーバーフローエラー発生

    ConfigIntTimer4(T4_INT_ON | T4_INT_PRIOR_1);
}


//---------------------------------------------------------------
void ProcessIO(void)
{
      BYTE i;
            App_Detect_Device();
            switch(App_State_Keyboard)
            {
                case DEVICE_NOT_CONNECTED:
                    USBTasks();
                    if(DisplayDeatachOnce == FALSE)
                    {

                        lcd_clear();
                        lcd_cmd(0x80);
                        sprintf(Buf,"Device Det");
                        lcd_str(Buf);

                     //   LCDDisplayString((BYTE*)"Device Detached ", LCD_LINE_ONE);
                        DisplayDeatachOnce = TRUE;
                    }
                    if(USBHostHID_ApiDeviceDetect()) /* True if report descriptor is parsed with no error */
                    {
                        App_State_Keyboard = DEVICE_CONNECTED;
                        DisplayConnectOnce = FALSE;
                    }
                    break;
                case DEVICE_CONNECTED:
                    App_State_Keyboard = READY_TO_TX_RX_REPORT;
                    if(DisplayConnectOnce == FALSE)
                    {
                        lcd_clear();
                        lcd_cmd(0x80);
                        sprintf(Buf,"EX16 Boare ");//
                        lcd_str(Buf);                   //液晶表示
                         lcd_cmd(0xC0);          //2行目の先頭へ
                         sprintf(Buf,"USB HIDHost Demo");     //
                         lcd_str(Buf);           // 開始メッセージ1行目表示
                        #ifdef DEBUG_MODE
                        UART2PrintString( "Explorer16 Board \r\n" );
                        UART2PrintString( "USB HIDHost Demo \r\n" );

                        #endif
                        DisplayConnectOnce = TRUE;
                        DisplayDeatachOnce = FALSE;
                    }
                    InitializeTimer(); // start 10ms timer to schedule input reports

                    break;
                case READY_TO_TX_RX_REPORT:
                    if(!USBHostHID_ApiDeviceDetect())
                    {


                        App_State_Keyboard = DEVICE_NOT_CONNECTED;
                        //                                DisplayOnce = FALSE;
                    }
                    break;
                case GET_INPUT_REPORT:



                    if(USBHostHID_ApiGetReport(Appl_raw_report_buffer.Report_ID,Appl_ModifierKeysDetails.interfaceNum,
                                Appl_raw_report_buffer.ReportSize, Appl_raw_report_buffer.ReportData))
                    {
                        /* Host may be busy/error -- keep trying */


                    }
                    else
                    {
                        App_State_Keyboard = INPUT_REPORT_PENDING;
                    }

                    USBTasks();
                    break;

                case INPUT_REPORT_PENDING:
                    if(USBHostHID_ApiTransferIsComplete(&ErrorDriver,&NumOfBytesRcvd))
                    {
                        if(ErrorDriver ||(NumOfBytesRcvd !=     Appl_raw_report_buffer.ReportSize ))
                        {
                            ErrorCounter++ ;
                            if(MAX_ERROR_COUNTER <= ErrorDriver)
                                App_State_Keyboard = ERROR_REPORTED;
                            else
                                App_State_Keyboard = READY_TO_TX_RX_REPORT;
                        }
                        else
                        {
                            ErrorCounter = 0;
                            ReportBufferUpdated = TRUE;
                            App_State_Keyboard = READY_TO_TX_RX_REPORT;

                            if(DisplayConnectOnce == TRUE)
                            {
                                for(i=0;i<Appl_raw_report_buffer.ReportSize;i++)
                                {
                                    if(Appl_raw_report_buffer.ReportData[i] != 0)
                                    {
                                        lcd_clear();
                                        lcd_cmd(0x80);
                                        DisplayConnectOnce = FALSE;
                                    }
                                }
                            }

                            App_ProcessInputReport();       //キーボード入力検出・表示
                            App_PrepareOutputReport();
                        }
                    }
                    break;

                case SEND_OUTPUT_REPORT: /* Will be done while implementing Keyboard */
                    if(USBHostHID_ApiSendReport(Appl_LED_Indicator.reportID,Appl_LED_Indicator.interfaceNum, Appl_LED_Indicator.reportLength,
                                (BYTE*)&Appl_led_report_buffer))
                    {
                        /* Host may be busy/error -- keep trying */
                    }
                    else
                    {
                        App_State_Keyboard = OUTPUT_REPORT_PENDING;
                    }
                    USBTasks();

                    break;
                case OUTPUT_REPORT_PENDING:
                    if(USBHostHID_ApiTransferIsComplete(&ErrorDriver,&NumOfBytesRcvd))
                    {
                        if(ErrorDriver)
                        {
                            ErrorCounter++ ;
                            if(MAX_ERROR_COUNTER <= ErrorDriver)
                                App_State_Keyboard = ERROR_REPORTED;

                            //                                App_State_Keyboard = READY_TO_TX_RX_REPORT;
                        }
                        else
                        {
                            ErrorCounter = 0;
                            App_State_Keyboard = READY_TO_TX_RX_REPORT;
                        }
                    }
                    break;

                case ERROR_REPORTED:
                    break;
                default:
                    break;

            }



}




/****************************************************************************
  Function:
    void App_PrepareOutputReport(void)

  Description:
    This function schedules output report if any LED indicator key is pressed.

  Precondition:
    None

  Parameters:
    None

  Return Values:
    None

  Remarks:
    None
***************************************************************************/
void App_PrepareOutputReport(void)
{
//    if((READY_TO_TX_RX_REPORT == App_State_Keyboard) && (ReportBufferUpdated == TRUE))
    if(ReportBufferUpdated == TRUE)
    {
        ReportBufferUpdated = FALSE;
        if(LED_Key_Pressed)
        {
            App_State_Keyboard = SEND_OUTPUT_REPORT;
            LED_Key_Pressed = FALSE;
        }
     }
}

/****************************************************************************
  Function:
    void App_ProcessInputReport(void)

  Description:
    This function processes input report received from HID device.

  Precondition:
    None

  Parameters:
    None

  Return Values:
    None

  Remarks:
    None
***************************************************************************/
void App_ProcessInputReport(void)
{
    BYTE  i;
    BYTE  data;
   /* process input report received from device */
    USBHostHID_ApiImportData(Appl_raw_report_buffer.ReportData, Appl_raw_report_buffer.ReportSize
                          ,Appl_BufferModifierKeys, &Appl_ModifierKeysDetails);
    USBHostHID_ApiImportData(Appl_raw_report_buffer.ReportData, Appl_raw_report_buffer.ReportSize
                          ,Appl_BufferNormalKeys, &Appl_NormalKeysDetails);

    for(i=0;i<(sizeof(Appl_BufferNormalKeys)/sizeof(Appl_BufferNormalKeys[0]));i++)
    {
        if(Appl_BufferNormalKeys[i] != 0)
        {
            if(Appl_BufferNormalKeys[i] == HID_CAPS_LOCK_VAL)
            {
               CAPS_Lock_Pressed = !CAPS_Lock_Pressed;
               LED_Key_Pressed = TRUE;
               Appl_led_report_buffer.CAPS_LOCK = CAPS_Lock_Pressed;
            }else if(Appl_BufferNormalKeys[i] == HID_NUM_LOCK_VAL)
            {
                NUM_Lock_Pressed = !NUM_Lock_Pressed;
                LED_Key_Pressed = TRUE;
                Appl_led_report_buffer.NUM_LOCK = NUM_Lock_Pressed;
            }else
            {
            /* check if key press was present in previous report */
            // if key press was pressed in previous report neglect it ????
               if(!App_CompareKeyPressedPrevBuf(Appl_BufferNormalKeys[i]))
                {
                   //アスキーコードに変換-----------------------------------------------------------------------------
                    data = App_HID2ASCII(Appl_BufferNormalKeys[i]);  // convert data to ascii
                    LCD_Display_Routine(data,Appl_BufferNormalKeys[i] );
                }
            }
        }
        else
        {
            if(i==0)
            {
                HeldKeyCount = 0;
            }
            else
            {
                if(Appl_BufferNormalKeys[i-1] == HeldKey)
                {
                    if(HeldKeyCount < 3)
                    {
                        HeldKeyCount++;
                    }
                    else
                    {
                        //アスキーコードに変換-----------------------------------------------------------------------------
                        data = App_HID2ASCII(HeldKey);  // convert data to ascii
                        LCD_Display_Routine(data,HeldKey );
                    }
                }
                else
                {
                    HeldKeyCount = 0;
                    HeldKey = Appl_BufferNormalKeys[i-1];
                }
            }
            break;
        }
      }
      App_CopyToShadowBuffer();
      App_Clear_Data_Buffer();
}

/****************************************************************************
  Function:
    void App_CopyToShadowBuffer(void)

  Description:
    This function updates the shadow buffers with previous reports.

  Precondition:
    None

  Parameters:
    None

  Return Values:
    None

  Remarks:
    None
***************************************************************************/
void App_CopyToShadowBuffer(void)
{
    BYTE i;

    for(i=0;i<(sizeof(Appl_BufferNormalKeys)/sizeof(Appl_BufferNormalKeys[0]));i++)
    {
        Appl_ShadowBuffer1[i] = Appl_BufferNormalKeys[i];
    }
}

/****************************************************************************
  Function:
    BOOL App_CompareKeyPressedPrevBuf(BYTE data)

  Description:
    This function compares if the data byte received in report was sent in
    previous report. This is to avoid duplication incase user key in strokes
    at fast rate.

  Precondition:
    None

  Parameters:
    BYTE data         -   data byte that needs to be compared with previous
                          report

  Return Values:
    None

  Remarks:
    None
***************************************************************************/
BOOL App_CompareKeyPressedPrevBuf(BYTE data)
{
    BYTE i;

    for(i=0;i<(sizeof(Appl_BufferNormalKeys)/sizeof(Appl_BufferNormalKeys[0]));i++)
    {
        if(data == Appl_ShadowBuffer1[i])
        {
            return TRUE;
        }
    }
    return FALSE;
}


/****************************************************************************
  Function:
    void App_Detect_Device(void)

  Description:
    This function monitors the status of device connected/disconnected

  Precondition:
    None

  Parameters:
    None

  Return Values:
    None

  Remarks:
    None
***************************************************************************/
void App_Detect_Device(void)
{
  if(!USBHostHID_ApiDeviceDetect())
  {
     App_State_Keyboard = DEVICE_NOT_CONNECTED;
  }
}

/****************************************************************************
  Function:
    void App_Clear_Data_Buffer(void)

  Description:
    This function clears the content of report buffer after reading

  Precondition:
    None

  Parameters:
    None

  Return Values:
    None

  Remarks:
    None
***************************************************************************/
void App_Clear_Data_Buffer(void)
{
    BYTE i;

    for(i=0;i<(sizeof(Appl_BufferNormalKeys)/sizeof(Appl_BufferNormalKeys[0]));i++)
    {
        Appl_BufferNormalKeys[i] = 0;
    }

    for(i=0;i<Appl_raw_report_buffer.ReportSize;i++)
    {
        Appl_raw_report_buffer.ReportData[i] = 0;
    }
}

/****************************************************************************
  Function:
    BYTE App_HID2ASCII(BYTE a)
  Description:
    This function converts the HID code of the key pressed to coressponding
    ASCII value. For Key strokes like Esc, Enter, Tab etc it returns 0.

  Precondition:
    None

  Parameters:
    BYTE a          -   HID code for the key pressed

  Return Values:
    BYTE            -   ASCII code for the key pressed

  Remarks:
    None
***************************************************************************/
BYTE App_HID2ASCII(BYTE a) //convert USB HID code (buffer[2 to 7]) to ASCII code
{
   BYTE AsciiVal;
   BYTE ShiftkeyStatus = 0;
   if((Appl_BufferModifierKeys[MODIFIER_LEFT_SHIFT] == 1)||(Appl_BufferModifierKeys[MODIFIER_RIGHT_SHIFT] == 1))
    {
        ShiftkeyStatus = 1;
    }

   if(a>=0x1E && a<=0x27)
    {
       if(ShiftkeyStatus)
        {
            switch(a)
            {
                case Symbol_Exclamation: AsciiVal = 0x21;
                    break;
                case Symbol_AT: AsciiVal = 0x40;
                    break;
                case Symbol_Pound: AsciiVal = 0x23;
                    break;
                case Symbol_Dollar: AsciiVal = 0x24;
                    break;
                case Symbol_Percentage: AsciiVal = 0x25;
                    break;
                case Symbol_Cap: AsciiVal = 0x5E;
                    break;
                case Symbol_AND: AsciiVal = 0x26;
                    break;
                case Symbol_Star: AsciiVal = 0x2A;
                    break;
                case Symbol_NormalBracketOpen: AsciiVal = 0x28;
                    break;
                case Symbol_NormalBracketClose: AsciiVal = 0x29;
                    break;
                default:
                    break;
            }

            return(AsciiVal);
        }
       else
       {
            if(a==0x27)
            {
                return(0x30);
            }
            else
            {
                return(a+0x13);
            }
       }
    }

   if((a>=0x59 && a<=0x61)&&(NUM_Lock_Pressed == 1))
    {
       return(a-0x28);
    }

   if((a==0x62) &&(NUM_Lock_Pressed == 1)) return(0x30);


   if(a>=0x04 && a<=0x1D)
    {
      if(((CAPS_Lock_Pressed == 1)&&((Appl_BufferModifierKeys[MODIFIER_LEFT_SHIFT] == 0)&&
                                (Appl_BufferModifierKeys[MODIFIER_RIGHT_SHIFT] == 0)))
          ||((CAPS_Lock_Pressed == 0)&&((Appl_BufferModifierKeys[MODIFIER_LEFT_SHIFT] == 1) ||
                                        (Appl_BufferModifierKeys[MODIFIER_RIGHT_SHIFT] == 1))))
           return(a+0x3d); /* return capital */
      else
           return(a+0x5d); /* return small case */
    }


   if(a>=0x2D && a<=0x38)
    {
        switch(a)
        {
            case Symbol_HyphenUnderscore:
                if(!ShiftkeyStatus)
                    AsciiVal = 0x2D;
                else
                    AsciiVal = 0x5F;
                break;
            case Symbol_EqualAdd:
                if(!ShiftkeyStatus)
                    AsciiVal = 0x3D;
                else
                    AsciiVal = 0x2B;
                break;
            case Symbol_BracketOpen:
                if(!ShiftkeyStatus)
                    AsciiVal = 0x5B;
                else
                    AsciiVal = 0x7B;
                break;
            case Symbol_BracketClose:
                if(!ShiftkeyStatus)
                    AsciiVal = 0x5D;
                else
                    AsciiVal = 0x7D;
                break;
            case Symbol_BackslashOR:
                if(!ShiftkeyStatus)
                    AsciiVal = 0x5C;
                else
                    AsciiVal = 0x7C;
                break;
            case Symbol_SemiColon:
                if(!ShiftkeyStatus)
                    AsciiVal = 0x3B;
                else
                    AsciiVal = 0x3A;
                break;
            case Symbol_InvertedComma:
                if(!ShiftkeyStatus)
                    AsciiVal = 0x27;
                else
                    AsciiVal = 0x22;
                break;
            case Symbol_Tilde:
                if(!ShiftkeyStatus)
                    AsciiVal = 0x60;
                else
                    AsciiVal = 0x7E;
                break;
            case Symbol_CommaLessThan:
                if(!ShiftkeyStatus)
                    AsciiVal = 0x2C;
                else
                    AsciiVal = 0x3C;
                break;
            case Symbol_PeriodGreaterThan:
                if(!ShiftkeyStatus)
                    AsciiVal = 0x2E;
                else
                    AsciiVal = 0x3E;
                break;
            case Symbol_FrontSlashQuestion:
                if(!ShiftkeyStatus)
                    AsciiVal = 0x2F;
                else
                    AsciiVal = 0x3F;
                break;
            default:
                break;
        }
        return(AsciiVal);
    }

   return(0);
}


/****************************************************************************
  Function:
    void LCD_Display_Routine(BYTE data , BYTE HIDData)
  Description:
    This function displays the key strokes on the LCD  mounted on Explorer16
    demo board.

  Precondition:
    None

  Parameters:
    BYTE data       -   ASCII code for the key pressed
    BYTE HIDData    -   HID code for the key pressed, this is needed to take
                        action for keys like Esc, Enter, Tab etc.

  Return Values:
    None

  Remarks:
***************************************************************************/

void LCD_Display_Routine(BYTE data , BYTE HIDData)
{
    BYTE LineNum;
    BYTE CharPos;

    int i;

    LineNum = ((currCharPos & 0x30) >> 4);
    CharPos = currCharPos & 0x0F;

    

   if(((HIDData>=0x1E && HIDData<=0x27) || (HIDData>=0x04 && HIDData<=0x1D) ||
          (HIDData>=0x2D && HIDData<=0x38) ||
          ((HIDData>=0x59 && HIDData<=0x62)&&(NUM_Lock_Pressed == 1))) && (HIDData != 0x35))    //0x35: 漢字キー追加
    {

        lcd_data(data);
        currCharPos++;


      
         if(myColumnNum == (myColumnNum0 - 1))
                       {
                           strncat(myAllChar,Kaigyou,16);   //改行記号\n 追加
                           myCharPos++;
                           myColumnNum = 0;  //列番号リセット
                           myLineNum++;
                           if(myLineNum == 13)
                           {
                                    //グラフィック液晶のStatic Text Widgetに表示
                                STATICTEXT *pSTE_1 = (STATICTEXT*)GOLFindObject(STE_1);    //エディットボックスのオブジェクト検出

                                pSTE_1->hdr.state = ST_DRAW;    //再描画により文字は左アラインにリセットされる
                                for(i = 0; i <1024; i++)tempBuf[i] = 0x00;

                                StSetText((STATICTEXT*)pSTE_1, myAllChar);    //
                                SetState(pSTE_1, ST_DRAW);
                           }

                       }

        
        sprintf(Buf,"%c",data);
        myCharPos++;
        myColumnNum++;

    }
    else if(HIDData == 0x29)    // escape key pressed
    {
        lcd_clear();
        lcd_cmd(0x80);
        currCharPos = 0;

     //   sprintf(Buf,"HID = 0x%x,  Key = ESC",HIDData,data,data);




    }
    else if (HIDData == 0x2C) //スペースが押された場合
    {
        lcd_data(0x20);    // /0x20: アスキー文字のスペース
        currCharPos++;

        data = 0x20;
        sprintf(Buf,"%c",data);
        myCharPos++;

    }
    else if (HIDData == Symbol_Backspace) //バックスペースが押された場合
    {
        if(currCharPos != 0)
        {
            lcd_cmd(0b00010000);
            lcd_data(0x20);    // space ascii value 0x20
            lcd_cmd(0b00010000);
            currCharPos--;
        }
          sprintf(Buf,"%c",0x00);   //0x20: アスキー文字のスペース
          myCharPos--;
          myColumnNum--;
          if(myColumnNum < 0)
          {
              myColumnNum = myColumnNum0;
              myLineNum--;
          }

          if(tempBuf[myCharPos] == '\n')myCharPos--;
          tempBuf[myCharPos] = 0x00;    //文字列終端記号\0をセット

    }
    else if((HIDData>=0x4F && HIDData<=0x52) ||
            (( HIDData==0x5C || HIDData==0x5E || HIDData==0x5A || HIDData==0x60  )
               && (NUM_Lock_Pressed == 0)))
    {
        switch(HIDData)
        {
            case 0x4F :   // Right Arrow
            case 0x5E :
                lcd_cmd(0b00010100);
                currCharPos++;
                 sprintf(Buf,"HID = 0x%x,  Key = Right Arrow",HIDData,data,data);
                break;

            case 0x50 :   // Left Arrow
            case 0x5C :
                lcd_cmd(0b00010000);
                currCharPos--;
                sprintf(Buf,"HID = 0x%x,  Key = Left Arrow",HIDData,data,data);
                break;

            case 0x52 :   // Up Arrow
            case 0x60 :
                if(LineNum == 1)
                {
//                    LCDShiftCursorUp();   //対応する関数なし
                    currCharPos = currCharPos - 16;
                    LineNum = 0;
                }
                sprintf(Buf,"HID = 0x%x,  Key = Up Arrow",HIDData,data,data);
                break;

            case 0x51 :   // Down Arrow
            case 0x5A :
                if(LineNum == 0)
                {
 //                   LCDShiftCursorDown(); //対応する関数なし
                    currCharPos = currCharPos + 16;
                    LineNum = 1;
                }
                sprintf(Buf,"HID = 0x%x,  Key = Down Arrow",HIDData,data,data);
                break;
            default :
                break;
        }

    }
    else if(HIDData == Symbol_Return)
    {
        
        sprintf(Buf,"\n");
        myCharPos++;
        myColumnNum = 0;
        myLineNum++;
        if(myLineNum == 13)
        {
        //グラフィック液晶のStatic Text Widgetに表示
            STATICTEXT *pSTE_1 = (STATICTEXT*)GOLFindObject(STE_1);    //エディットボックスのオブジェクト検出
            pSTE_1->hdr.state = ST_DRAW;    //再描画により文字は左アラインにリセットされる
            for(i = 0; i <1024; i++)tempBuf[i] = 0x00;
            StSetText((STATICTEXT*)pSTE_1, myAllChar);    //
            SetState(pSTE_1, ST_DRAW);
       }
        

     //    sprintf(Buf,"HID = 0x%x,  Key = Return",HIDData,data,data);

    }
    else if(HIDData == Symbol_Kanji)
    {
     //    sprintf(Buf,"HID = 0x%x,  Key = Kanji",HIDData,data,data);

    }
    else if(HIDData == Symbol_Tab)
    {
    //     sprintf(Buf,"HID = 0x%x,  Key = Tab",HIDData,data,data);

    }
    else if(HIDData == Symbol_Delete)
    {
      //   sprintf(Buf,"HID = 0x%x,  Key = Delete",HIDData,data,data);

    }
    else if(HIDData == Symbol_PrintScr)
    {
     //    sprintf(Buf,"HID = 0x%x,  Key = PrintScr",HIDData,data,data);

    }
    else if(HIDData == Symbol_PauseBreak)
    {
     //    sprintf(Buf,"HID = 0x%x,  Key = PauseBreak",HIDData,data,data);

    }
    else if(HIDData == Symbol_ScrLK)
    {
     //    sprintf(Buf,"HID = 0x%x,  Key = ScrLK",HIDData,data,data);

    }
    
    
     else
    {
         sprintf(Buf,"HID = 0x%x,  Key = ?",HIDData,data,data);

    }

        //グラフィック液晶のStatic Text Widgetに表示
    STATICTEXT *pSTE_1 = (STATICTEXT*)GOLFindObject(STE_1);    //エディットボックスのオブジェクト検出

    pSTE_1->hdr.state = ST_DRAW;    //再描画により文字は左アラインにリセットされる

    strncat(myAllChar,Buf,65);      //文字追加

    StSetText((STATICTEXT*)pSTE_1, myAllChar);    //
    SetState(pSTE_1, ST_DRAW);

    LineNum = ((currCharPos & 0x30) >> 4);
    CharPos = currCharPos & 0x0F;

    if((LineNum == 1) && (CharPos == 0x0))
    {
        lcd_cmd(0xC0);
        currCharPos = 0x10;
    }else if((LineNum == 2) && (CharPos == 0x0))
    {
        lcd_clear();
        lcd_cmd(0x80);
        currCharPos = 0;
    }

   if(currCharPos > 0x20)
    {
        lcd_clear();
        lcd_cmd(0x80);
        currCharPos = 0;
    }

}




/****************************************************************************
  Function:
    BOOL USB_HID_DataCollectionHandler(void)
  Description:
    This function is invoked by HID client , purpose is to collect the
    details extracted from the report descriptor. HID client will store
    information extracted from the report descriptor in data structures.
    Application needs to create object for each report type it needs to
    extract.
    For ex: HID_DATA_DETAILS Appl_ModifierKeysDetails;
    HID_DATA_DETAILS is defined in file usb_host_hid_appl_interface.h
    Each member of the structure must be initialized inside this function.
    Application interface layer provides functions :
    USBHostHID_ApiFindBit()
    USBHostHID_ApiFindValue()
    These functions can be used to fill in the details as shown in the demo
    code.

  Precondition:
    None

  Parameters:
    None

  Return Values:
    TRUE    - If the report details are collected successfully.
    FALSE   - If the application does not find the the supported format.

  Remarks:
    This Function name should be entered in the USB configuration tool
    in the field "Parsed Data Collection handler".
    If the application does not define this function , then HID cient
    assumes that Application is aware of report format of the attached
    device.
***************************************************************************/
BOOL USB_HID_DataCollectionHandler(void)
{
  BYTE NumOfReportItem = 0;
  BYTE i;
  USB_HID_ITEM_LIST* pitemListPtrs;
  USB_HID_DEVICE_RPT_INFO* pDeviceRptinfo;
  HID_REPORTITEM *reportItem;
  HID_USAGEITEM *hidUsageItem;
  BYTE usageIndex;
  BYTE reportIndex;
  BOOL foundLEDIndicator = FALSE;
  BOOL foundModifierKey = FALSE;
  BOOL foundNormalKey = FALSE;



  pDeviceRptinfo = USBHostHID_GetCurrentReportInfo(); // Get current Report Info pointer
  pitemListPtrs = USBHostHID_GetItemListPointers();   // Get pointer to list of item pointers

  BOOL status = FALSE;
   /* Find Report Item Index for Modifier Keys */
   /* Once report Item is located , extract information from data structures provided by the parser */
   NumOfReportItem = pDeviceRptinfo->reportItems;
   for(i=0;i<NumOfReportItem;i++)
    {
       reportItem = &pitemListPtrs->reportItemList[i];
       if((reportItem->reportType==hidReportInput) && (reportItem->dataModes == HIDData_Variable)&&
           (reportItem->globals.usagePage==USAGE_PAGE_KEY_CODES))
        {
           /* We now know report item points to modifier keys */
           /* Now make sure usage Min & Max are as per application */
            usageIndex = reportItem->firstUsageItem;
            hidUsageItem = &pitemListPtrs->usageItemList[usageIndex];
            if((hidUsageItem->usageMinimum == USAGE_MIN_MODIFIER_KEY)
                &&(hidUsageItem->usageMaximum == USAGE_MAX_MODIFIER_KEY)) //else application cannot suuport
            {
               reportIndex = reportItem->globals.reportIndex;
               Appl_ModifierKeysDetails.reportLength = (pitemListPtrs->reportList[reportIndex].inputBits + 7)/8;
               Appl_ModifierKeysDetails.reportID = (BYTE)reportItem->globals.reportID;
               Appl_ModifierKeysDetails.bitOffset = (BYTE)reportItem->startBit;
               Appl_ModifierKeysDetails.bitLength = (BYTE)reportItem->globals.reportsize;
               Appl_ModifierKeysDetails.count=(BYTE)reportItem->globals.reportCount;
               Appl_ModifierKeysDetails.interfaceNum= USBHostHID_ApiGetCurrentInterfaceNum();
               foundModifierKey = TRUE;
            }

        }
        else if((reportItem->reportType==hidReportInput) && (reportItem->dataModes == HIDData_Array)&&
           (reportItem->globals.usagePage==USAGE_PAGE_KEY_CODES))
        {
           /* We now know report item points to modifier keys */
           /* Now make sure usage Min & Max are as per application */
            usageIndex = reportItem->firstUsageItem;
            hidUsageItem = &pitemListPtrs->usageItemList[usageIndex];
            if((hidUsageItem->usageMinimum == USAGE_MIN_NORMAL_KEY)
                &&(hidUsageItem->usageMaximum <= USAGE_MAX_NORMAL_KEY)) //else application cannot suuport
            {
               reportIndex = reportItem->globals.reportIndex;
               Appl_NormalKeysDetails.reportLength = (pitemListPtrs->reportList[reportIndex].inputBits + 7)/8;
               Appl_NormalKeysDetails.reportID = (BYTE)reportItem->globals.reportID;
               Appl_NormalKeysDetails.bitOffset = (BYTE)reportItem->startBit;
               Appl_NormalKeysDetails.bitLength = (BYTE)reportItem->globals.reportsize;
               Appl_NormalKeysDetails.count=(BYTE)reportItem->globals.reportCount;
               Appl_NormalKeysDetails.interfaceNum= USBHostHID_ApiGetCurrentInterfaceNum();
               foundNormalKey = TRUE;
            }

        }
        else if((reportItem->reportType==hidReportOutput) &&
                (reportItem->globals.usagePage==USAGE_PAGE_LEDS))
        {
            usageIndex = reportItem->firstUsageItem;
            hidUsageItem = &pitemListPtrs->usageItemList[usageIndex];

            reportIndex = reportItem->globals.reportIndex;
            Appl_LED_Indicator.reportLength = (pitemListPtrs->reportList[reportIndex].outputBits + 7)/8;
            Appl_LED_Indicator.reportID = (BYTE)reportItem->globals.reportID;
            Appl_LED_Indicator.bitOffset = (BYTE)reportItem->startBit;
            Appl_LED_Indicator.bitLength = (BYTE)reportItem->globals.reportsize;
            Appl_LED_Indicator.count=(BYTE)reportItem->globals.reportCount;
            Appl_LED_Indicator.interfaceNum= USBHostHID_ApiGetCurrentInterfaceNum();
            foundLEDIndicator = TRUE;
        }

    }


   if(pDeviceRptinfo->reports == 1)
    {
        Appl_raw_report_buffer.Report_ID = 0;
        Appl_raw_report_buffer.ReportSize = (pitemListPtrs->reportList[reportIndex].inputBits + 7)/8;
        Appl_raw_report_buffer.ReportData = (BYTE*)malloc(Appl_raw_report_buffer.ReportSize);
        Appl_raw_report_buffer.ReportPollRate = pDeviceRptinfo->reportPollingRate;
        if((foundNormalKey == TRUE)&&(foundModifierKey == TRUE))
        status = TRUE;
    }

    return(status);
}

/****************************************************************************
  Function:
     void InitializeTimer( void )

  Description:
    This function initializes the tick timer.  It configures and starts the
    timer, and enables the timer interrupt.

  Precondition:
    None

  Parameters:
    None

  Returns:
    None

  Remarks:
    None
  ***************************************************************************/


void InitializeTimer( void )    //タイマ4 → タイマ5に変更 //GDDXのインターバルタイマ(タイマ4)とバッティング回避 
{
    //TODO - PIC32 support
    T5CON = 0x0; //Stop and Init Timer
  //  T4CON = 0x0; //Stop and Init Timer
     T5CON = 0x0060;
 //   T4CON = 0x0060;
    //prescaler=1:64,
    //internal clock
      TMR5 = 0; //Clear timer register

  //  TMR4 = 0; //Clear timer register


  PR5 = 0x7FFF; //Load period register
  //PR4 = 0x7FFF; //Load period register
 //1000/80000000*64*0x7FFF(32767) = 26.2msec
 //    OpenTimer4(T4_ON | T4_PS_1_256, 31249);      //1000/80000000*256*31249 =99.9968 msec

IPC5SET = 0x00000004; // Set priority level=1 and
 //   IPC4SET = 0x00000004; // Set priority level=1 and

 IPC5SET = 0x00000001; // Set subpriority level=1
 //   IPC4SET = 0x00000001; // Set subpriority level=1
    // Could have also done this in single
    // operation by assigning IPC5SET = 0x00000005

//    IFS0CLR = 0x00010000; // Clear the Timer5 interrupt status flag
//    IEC0SET = 0x00010000; // Enable Timer5 interrupts


    IFS0bits.T5IF = 0;
 //   IFS0bits.T4IF = 0;
    IEC0bits.T5IE = 1;
//    IEC0bits.T4IE = 1;

      T5CONSET = 0x8000;//Start Timer

  //  T4CONSET = 0x8000;//Start Timer
    return;
}

/****************************************************************************
  Function:
    void __attribute__((__interrupt__, auto_psv)) _T3Interrupt(void)

  Description:
    Timer ISR, used to update application state. If no transfers are pending
    new input request is scheduled.
  Precondition:
    None

  Parameters:
    None

  Return Values:
    None

  Remarks:
    None
  ***************************************************************************/

#pragma interrupt _T5Interrupt ipl4 vector 20   //タイマ5   //割込みレベル:4 //ベクター番号:20
//#pragma interrupt _T4Interrupt ipl4 vector 16
void _T5Interrupt(void)
//void _T4Interrupt( void )
{
    if(myMode == 0)
    {
        myMode = 1;
        LATDbits.LATD3 = 0;
    }
    else
    {
        myMode = 0;
        LATDbits.LATD3 = 1;
    }

 if (IFS0bits.T5IF)
  //  if (IFS0bits.T4IF)
    {
     IFS0bits.T5IF   = 0;
     //   IFS0bits.T4IF   = 0;
        if(READY_TO_TX_RX_REPORT == App_State_Keyboard)
        {
            App_State_Keyboard = GET_INPUT_REPORT; // If no report is pending schedule new request
        }
    }
}



 // USB Support Functions

BOOL USB_ApplicationEventHandler( BYTE address, USB_EVENT event, void *data, DWORD size )
{
    switch( (INT)event )
    {
        case EVENT_VBUS_REQUEST_POWER:
            // The data pointer points to a byte that represents the amount of power
            // requested in mA, divided by two.  If the device wants too much power,
            // we reject it.
            if (((USB_VBUS_POWER_EVENT_DATA*)data)->current <= (MAX_ALLOWED_CURRENT / 2))
            {
                return TRUE;
            }
            else
            {
                UART2PrintString( "\r\n***** USB Error - device requires too much current *****\r\n" );
            }
            break;

        case EVENT_VBUS_RELEASE_POWER:
            // Turn off Vbus power.
            // The PIC24F with the Explorer 16 cannot turn off Vbus through software.
            return TRUE;
            break;

        case EVENT_HUB_ATTACH:
            UART2PrintString( "\r\n***** USB Error - hubs are not supported *****\r\n" );
            return TRUE;
            break;

        case EVENT_UNSUPPORTED_DEVICE:
            UART2PrintString( "\r\n***** USB Error - device is not supported *****\r\n" );
            return TRUE;
            break;

        case EVENT_CANNOT_ENUMERATE:
            UART2PrintString( "\r\n***** USB Error - cannot enumerate device *****\r\n" );
            return TRUE;
            break;

        case EVENT_CLIENT_INIT_ERROR:
            UART2PrintString( "\r\n***** USB Error - client driver initialization error *****\r\n" );
            return TRUE;
            break;

        case EVENT_OUT_OF_MEMORY:
            UART2PrintString( "\r\n***** USB Error - out of heap memory *****\r\n" );
            return TRUE;
            break;

        case EVENT_UNSPECIFIED_ERROR:   // This should never be generated.
            UART2PrintString( "\r\n***** USB Error - unspecified *****\r\n" );
            return TRUE;
            break;

                case EVENT_HID_RPT_DESC_PARSED:
                         #ifdef APPL_COLLECT_PARSED_DATA
                             return(APPL_COLLECT_PARSED_DATA());
                     #else
                                 return TRUE;
                         #endif
                        break;

        default:
            break;
    }
    return FALSE;
}
 













//その他 FAT、グラフィックライブラリ関連のインクルードファイルは下記にあります。
//マイクロチップのライブラリダウンロードページ: Microchip Libraries for Applications  私がつかったバージョンは \microchip_solutions_v2013-02-15 です。
//GDDX関連のファイルは Microchip Graphics Display Designer X からダウンロードできます。 私がつかったバージョンは GDDX v.1.10 です
//グラフィック液晶INT035TFTの関連情報は Displaytechのホームページ 及び DisplaytechのForum  にあります。



<実行結果>


 




   <プログラム例>

main() { }